diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/AttributeList.cpp | 145 | ||||
-rw-r--r-- | lib/Parse/DeclSpec.cpp | 25 | ||||
-rw-r--r-- | lib/Parse/MinimalAction.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 359 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 60 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 168 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 623 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 146 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 32 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 84 |
11 files changed, 1023 insertions, 627 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 224a31c..344ce9e 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/AttributeList.h" #include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc, @@ -52,94 +53,58 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { AttrName = AttrName.substr(2, AttrName.size() - 4); // FIXME: Hand generating this is neither smart nor efficient. - const char *Str = AttrName.data(); - switch (AttrName.size()) { - case 4: - if (!memcmp(Str, "weak", 4)) return AT_weak; - if (!memcmp(Str, "pure", 4)) return AT_pure; - if (!memcmp(Str, "mode", 4)) return AT_mode; - if (!memcmp(Str, "used", 4)) return AT_used; - break; - case 5: - if (!memcmp(Str, "alias", 5)) return AT_alias; - if (!memcmp(Str, "const", 5)) return AT_const; - break; - case 6: - if (!memcmp(Str, "packed", 6)) return AT_packed; - if (!memcmp(Str, "malloc", 6)) return AT_malloc; - if (!memcmp(Str, "format", 6)) return AT_format; - if (!memcmp(Str, "unused", 6)) return AT_unused; - if (!memcmp(Str, "blocks", 6)) return AT_blocks; - break; - case 7: - if (!memcmp(Str, "aligned", 7)) return AT_aligned; - if (!memcmp(Str, "cleanup", 7)) return AT_cleanup; - if (!memcmp(Str, "nodebug", 7)) return AT_nodebug; - if (!memcmp(Str, "nonnull", 7)) return AT_nonnull; - if (!memcmp(Str, "nothrow", 7)) return AT_nothrow; - if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc; - if (!memcmp(Str, "regparm", 7)) return AT_regparm; - if (!memcmp(Str, "section", 7)) return AT_section; - if (!memcmp(Str, "stdcall", 7)) return AT_stdcall; - break; - case 8: - if (!memcmp(Str, "annotate", 8)) return AT_annotate; - if (!memcmp(Str, "noreturn", 8)) return AT_noreturn; - if (!memcmp(Str, "noinline", 8)) return AT_noinline; - if (!memcmp(Str, "fastcall", 8)) return AT_fastcall; - if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet; - if (!memcmp(Str, "sentinel", 8)) return AT_sentinel; - if (!memcmp(Str, "NSObject", 8)) return AT_nsobject; - break; - case 9: - if (!memcmp(Str, "dllimport", 9)) return AT_dllimport; - if (!memcmp(Str, "dllexport", 9)) return AT_dllexport; - if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA - break; - case 10: - if (!memcmp(Str, "deprecated", 10)) return AT_deprecated; - if (!memcmp(Str, "visibility", 10)) return AT_visibility; - if (!memcmp(Str, "destructor", 10)) return AT_destructor; - if (!memcmp(Str, "format_arg", 10)) return AT_format_arg; - if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline; - break; - case 11: - if (!memcmp(Str, "weak_import", 11)) return AT_weak_import; - if (!memcmp(Str, "vector_size", 11)) return AT_vector_size; - if (!memcmp(Str, "constructor", 11)) return AT_constructor; - if (!memcmp(Str, "unavailable", 11)) return AT_unavailable; - break; - case 12: - if (!memcmp(Str, "overloadable", 12)) return AT_overloadable; - break; - case 13: - if (!memcmp(Str, "address_space", 13)) return AT_address_space; - if (!memcmp(Str, "always_inline", 13)) return AT_always_inline; - if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute; - break; - case 14: - if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception; - break; - case 15: - if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type; - break; - case 17: - if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union; - if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn; - break; - case 18: - if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result; - break; - case 19: - if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained; - if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained; - break; - case 20: - if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size; - case 22: - if (!memcmp(Str, "no_instrument_function", 22)) - return AT_no_instrument_function; - break; - } - return UnknownAttribute; + return llvm::StringSwitch<AttributeList::Kind>(AttrName) + .Case("weak", AT_weak) + .Case("pure", AT_pure) + .Case("mode", AT_mode) + .Case("used", AT_used) + .Case("alias", AT_alias) + .Case("const", AT_const) + .Case("packed", AT_packed) + .Case("malloc", AT_malloc) + .Case("format", AT_format) + .Case("unused", AT_unused) + .Case("blocks", AT_blocks) + .Case("aligned", AT_aligned) + .Case("cleanup", AT_cleanup) + .Case("nodebug", AT_nodebug) + .Case("nonnull", AT_nonnull) + .Case("nothrow", AT_nothrow) + .Case("objc_gc", AT_objc_gc) + .Case("regparm", AT_regparm) + .Case("section", AT_section) + .Case("stdcall", AT_stdcall) + .Case("annotate", AT_annotate) + .Case("noreturn", AT_noreturn) + .Case("noinline", AT_noinline) + .Case("fastcall", AT_fastcall) + .Case("iboutlet", AT_IBOutlet) + .Case("sentinel", AT_sentinel) + .Case("NSObject", AT_nsobject) + .Case("dllimport", AT_dllimport) + .Case("dllexport", AT_dllexport) + .Case("may_alias", IgnoredAttribute) // FIXME: TBAA + .Case("deprecated", AT_deprecated) + .Case("visibility", AT_visibility) + .Case("destructor", AT_destructor) + .Case("format_arg", AT_format_arg) + .Case("gnu_inline", AT_gnu_inline) + .Case("weak_import", AT_weak_import) + .Case("vector_size", AT_vector_size) + .Case("constructor", AT_constructor) + .Case("unavailable", AT_unavailable) + .Case("overloadable", AT_overloadable) + .Case("address_space", AT_address_space) + .Case("always_inline", AT_always_inline) + .Case("vec_type_hint", IgnoredAttribute) + .Case("objc_exception", AT_objc_exception) + .Case("ext_vector_type", AT_ext_vector_type) + .Case("transparent_union", AT_transparent_union) + .Case("analyzer_noreturn", AT_analyzer_noreturn) + .Case("warn_unused_result", AT_warn_unused_result) + .Case("ns_returns_retained", AT_ns_returns_retained) + .Case("cf_returns_retained", AT_cf_returns_retained) + .Case("reqd_work_group_size", AT_reqd_wg_size) + .Case("no_instrument_function", AT_no_instrument_function) + .Default(UnknownAttribute); } diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index b8422aa..3436900 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -446,3 +446,28 @@ bool DeclSpec::isMissingDeclaratorOk() { || tst == TST_enum ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef; } + +void UnqualifiedId::clear() { + if (Kind == IK_TemplateId) + TemplateId->Destroy(); + + Kind = IK_Identifier; + Identifier = 0; + StartLocation = SourceLocation(); + EndLocation = SourceLocation(); +} + +void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]) { + Kind = IK_OperatorFunctionId; + StartLocation = OperatorLoc; + EndLocation = OperatorLoc; + OperatorFunctionId.Operator = Op; + for (unsigned I = 0; I != 3; ++I) { + OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); + + if (SymbolLocations[I].isValid()) + EndLocation = SymbolLocations[I]; + } +} diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 71b22ca..1e7d397 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -161,9 +161,8 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *, TemplateNameKind MinimalAction::isTemplateName(Scope *S, - const IdentifierInfo &II, - SourceLocation IdLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringScope, TemplateTy &TemplateDecl) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b56c331..e905553 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -336,10 +336,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// If RequireSemi is false, this does not check for a ';' at the end of the /// declaration. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, - SourceLocation &DeclEnd, - bool RequireSemi) { + SourceLocation &DeclEnd) { // Parse the common declaration-specifiers piece. - DeclSpec DS; + ParsingDeclSpec DS(*this); ParseDeclarationSpecifiers(DS); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" @@ -347,32 +346,109 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, if (Tok.is(tok::semi)) { ConsumeToken(); DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } - Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); - ParseDeclarator(DeclaratorInfo); + DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, + &DeclEnd); + return DG; +} - DeclGroupPtrTy DG = - ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); +/// ParseDeclGroup - Having concluded that this is either a function +/// definition or a group of object declarations, actually parse the +/// result. +Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, + unsigned Context, + bool AllowFunctionDefinitions, + SourceLocation *DeclEnd) { + // Parse the first declarator. + ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context)); + ParseDeclarator(D); + + // Bail out if the first declarator didn't seem well-formed. + if (!D.hasName() && !D.mayOmitIdentifier()) { + // Skip until ; or }. + SkipUntil(tok::r_brace, true, true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return DeclGroupPtrTy(); + } + + if (AllowFunctionDefinitions && D.isFunctionDeclarator()) { + if (isDeclarationAfterDeclarator()) { + // Fall though. We have to check this first, though, because + // __attribute__ might be the start of a function definition in + // (extended) K&R C. + } else if (isStartOfFunctionDefinition()) { + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { + Diag(Tok, diag::err_function_declared_typedef); + + // Recover by treating the 'typedef' as spurious. + DS.ClearStorageClassSpecs(); + } - DeclEnd = Tok.getLocation(); + DeclPtrTy TheDecl = ParseFunctionDefinition(D); + return Actions.ConvertDeclToDeclGroup(TheDecl); + } else { + Diag(Tok, diag::err_expected_fn_body); + SkipUntil(tok::semi); + return DeclGroupPtrTy(); + } + } - // If the client wants to check what comes after the declaration, just return - // immediately without checking anything! - if (!RequireSemi) return DG; + llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; + DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D); + D.complete(FirstDecl); + if (FirstDecl.get()) + DeclsInGroup.push_back(FirstDecl); - if (Tok.is(tok::semi)) { + // If we don't have a comma, it is either the end of the list (a ';') or an + // error, bail out. + while (Tok.is(tok::comma)) { + // Consume the comma. ConsumeToken(); - return DG; + + // Parse the next declarator. + D.clear(); + + // Accept attributes in an init-declarator. In the first declarator in a + // declaration, these would be part of the declspec. In subsequent + // declarators, they become part of the declarator itself, so that they + // don't apply to declarators after *this* one. Examples: + // short __attribute__((common)) var; -> declspec + // short var __attribute__((common)); -> declarator + // short x, __attribute__((common)) var; -> declarator + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + D.AddAttributes(AttrList, Loc); + } + + ParseDeclarator(D); + + DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D); + D.complete(ThisDecl); + if (ThisDecl.get()) + DeclsInGroup.push_back(ThisDecl); } - Diag(Tok, diag::err_expected_semi_declaration); - // Skip to end of block or statement - SkipUntil(tok::r_brace, true, true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return DG; + if (DeclEnd) + *DeclEnd = Tok.getLocation(); + + if (Context != Declarator::ForContext && + ExpectAndConsume(tok::semi, + Context == Declarator::FileContext + ? diag::err_invalid_token_after_toplevel_declarator + : diag::err_expected_semi_declaration)) { + SkipUntil(tok::r_brace, true, true); + if (Tok.is(tok::semi)) + ConsumeToken(); + } + + return Actions.FinalizeDeclaratorGroup(CurScope, DS, + DeclsInGroup.data(), + DeclsInGroup.size()); } /// \brief Parse 'declaration' after parsing 'declaration-specifiers @@ -498,63 +574,6 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, return ThisDecl; } -/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after -/// parsing 'declaration-specifiers declarator'. This method is split out this -/// way to handle the ambiguity between top-level function-definitions and -/// declarations. -/// -/// init-declarator-list: [C99 6.7] -/// init-declarator -/// init-declarator-list ',' init-declarator -/// -/// According to the standard grammar, =default and =delete are function -/// definitions, but that definitely doesn't fit with the parser here. -/// -Parser::DeclGroupPtrTy Parser:: -ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { - // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls - // that we parse together here. - llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; - - // At this point, we know that it is not a function definition. Parse the - // rest of the init-declarator-list. - while (1) { - DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D); - if (ThisDecl.get()) - DeclsInGroup.push_back(ThisDecl); - - // If we don't have a comma, it is either the end of the list (a ';') or an - // error, bail out. - if (Tok.isNot(tok::comma)) - break; - - // Consume the comma. - ConsumeToken(); - - // Parse the next declarator. - D.clear(); - - // Accept attributes in an init-declarator. In the first declarator in a - // declaration, these would be part of the declspec. In subsequent - // declarators, they become part of the declarator itself, so that they - // don't apply to declarators after *this* one. Examples: - // short __attribute__((common)) var; -> declspec - // short var __attribute__((common)); -> declarator - // short x, __attribute__((common)) var; -> declarator - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); - D.AddAttributes(AttrList, Loc); - } - - ParseDeclarator(D); - } - - return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(), - DeclsInGroup.data(), - DeclsInGroup.size()); -} - /// ParseSpecifierQualifierList /// specifier-qualifier-list: /// type-specifier specifier-qualifier-list[opt] @@ -1468,8 +1487,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, /// [GNU] declarator[opt] ':' constant-expression attributes[opt] /// void Parser:: -ParseStructDeclaration(DeclSpec &DS, - llvm::SmallVectorImpl<FieldDeclarator> &Fields) { +ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -1489,9 +1507,17 @@ ParseStructDeclaration(DeclSpec &DS, } // Read struct-declarators until we find the semicolon. - Fields.push_back(FieldDeclarator(DS)); + bool FirstDeclarator = true; while (1) { - FieldDeclarator &DeclaratorInfo = Fields.back(); + ParsingDeclRAIIObject PD(*this); + FieldDeclarator DeclaratorInfo(DS); + + // Attributes are only allowed here on successive declarators. + if (!FirstDeclarator && Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.D.AddAttributes(AttrList, Loc); + } /// struct-declarator: declarator /// struct-declarator: declarator[opt] ':' constant-expression @@ -1514,6 +1540,10 @@ ParseStructDeclaration(DeclSpec &DS, DeclaratorInfo.D.AddAttributes(AttrList, Loc); } + // We're done with this declarator; invoke the callback. + DeclPtrTy D = Fields.invoke(DeclaratorInfo); + PD.complete(D); + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. if (Tok.isNot(tok::comma)) @@ -1522,15 +1552,7 @@ ParseStructDeclaration(DeclSpec &DS, // Consume the comma. ConsumeToken(); - // Parse the next declarator. - Fields.push_back(FieldDeclarator(DS)); - - // Attributes are only allowed on the second declarator. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); - Fields.back().D.AddAttributes(AttrList, Loc); - } + FirstDeclarator = false; } } @@ -1562,7 +1584,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, << DeclSpec::getSpecifierName((DeclSpec::TST)TagType); llvm::SmallVector<DeclPtrTy, 32> FieldDecls; - llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; // While we still have something to read, read the declarations in the struct. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { @@ -1578,28 +1599,28 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // Parse all the comma separated declarators. DeclSpec DS; - FieldDeclarators.clear(); + if (!Tok.is(tok::at)) { - ParseStructDeclaration(DS, FieldDeclarators); - - // Convert them all to fields. - for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { - FieldDeclarator &FD = FieldDeclarators[i]; - DeclPtrTy Field; - // Install the declarator into the current TagDecl. - if (FD.D.getExtension()) { - // Silences extension warnings - ExtensionRAIIObject O(Diags); - Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); - } else { - Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); + struct CFieldCallback : FieldCallback { + Parser &P; + DeclPtrTy TagDecl; + llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls; + + CFieldCallback(Parser &P, DeclPtrTy TagDecl, + llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) : + P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {} + + virtual DeclPtrTy invoke(FieldDeclarator &FD) { + // Install the declarator into the current TagDecl. + DeclPtrTy Field = P.Actions.ActOnField(P.CurScope, TagDecl, + FD.D.getDeclSpec().getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + FieldDecls.push_back(Field); + return Field; } - FieldDecls.push_back(Field); - } + } Callback(*this, TagDecl, FieldDecls); + + ParseStructDeclaration(DS, Callback); } else { // Handle @defs ConsumeToken(); if (!Tok.isObjCAtKeyword(tok::objc_defs)) { @@ -2107,7 +2128,6 @@ void Parser::ParseDeclarator(Declarator &D) { /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] void Parser::ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser) { - if (Diags.hasAllExtensionsSilenced()) D.setExtension(); // C++ member pointers start with a '::' or a nested-name. @@ -2270,97 +2290,47 @@ void Parser::ParseDeclaratorInternal(Declarator &D, void Parser::ParseDirectDeclarator(Declarator &D) { DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); - if (getLang().CPlusPlus) { - if (D.mayHaveIdentifier()) { - // ParseDeclaratorInternal might already have parsed the scope. - bool afterCXXScope = D.getCXXScopeSpec().isSet() || - ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0, - true); - if (afterCXXScope) { - // Change the declaration context for name lookup, until this function - // is exited (and the declarator has been parsed). - DeclScopeObj.EnterDeclaratorScope(); - } - - if (Tok.is(tok::identifier)) { - assert(Tok.getIdentifierInfo() && "Not an identifier?"); - - // If this identifier is the name of the current class, it's a - // constructor name. - if (!D.getDeclSpec().hasTypeSpecifier() && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) { - CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; - D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope, SS), - Tok.getLocation()); - // This is a normal identifier. - } else - D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); - ConsumeToken(); - goto PastIdentifier; - } else if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - - D.setTemplateId(TemplateId); - ConsumeToken(); - goto PastIdentifier; - } else if (Tok.is(tok::kw_operator)) { - SourceLocation OperatorLoc = Tok.getLocation(); - SourceLocation EndLoc; - - // First try the name of an overloaded operator - if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) { - D.setOverloadedOperator(Op, OperatorLoc, EndLoc); - } else { - // This must be a conversion function (C++ [class.conv.fct]). - if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc)) - D.setConversionFunction(ConvType, OperatorLoc, EndLoc); - else { - D.SetIdentifier(0, Tok.getLocation()); - } - } - goto PastIdentifier; - } else if (Tok.is(tok::tilde)) { - // This should be a C++ destructor. - SourceLocation TildeLoc = ConsumeToken(); - if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { - // FIXME: Inaccurate. - SourceLocation NameLoc = Tok.getLocation(); - SourceLocation EndLoc; - CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; - TypeResult Type = ParseClassName(EndLoc, SS, true); - if (Type.isInvalid()) - D.SetIdentifier(0, TildeLoc); - else - D.setDestructor(Type.get(), TildeLoc, NameLoc); - } else { - Diag(Tok, diag::err_destructor_class_name); - D.SetIdentifier(0, TildeLoc); - } - goto PastIdentifier; - } - - // If we reached this point, token is not identifier and not '~'. - - if (afterCXXScope) { - Diag(Tok, diag::err_expected_unqualified_id); + if (getLang().CPlusPlus && D.mayHaveIdentifier()) { + // ParseDeclaratorInternal might already have parsed the scope. + bool afterCXXScope = D.getCXXScopeSpec().isSet() || + ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0, + true); + if (afterCXXScope) { + // Change the declaration context for name lookup, until this function + // is exited (and the declarator has been parsed). + DeclScopeObj.EnterDeclaratorScope(); + } + + if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) || + Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { + // We found something that indicates the start of an unqualified-id. + // Parse that unqualified-id. + if (ParseUnqualifiedId(D.getCXXScopeSpec(), + /*EnteringContext=*/true, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(), + /*ObjectType=*/0, + D.getName())) { D.SetIdentifier(0, Tok.getLocation()); D.setInvalidType(true); - goto PastIdentifier; + } else { + // Parsed the unqualified-id; update range information and move along. + if (D.getSourceRange().getBegin().isInvalid()) + D.SetRangeBegin(D.getName().getSourceRange().getBegin()); + D.SetRangeEnd(D.getName().getSourceRange().getEnd()); } + goto PastIdentifier; } - } - - // If we reached this point, we are either in C/ObjC or the token didn't - // satisfy any of the C++-specific checks. - if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { + } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { assert(!getLang().CPlusPlus && "There's a C++-specific check for tok::identifier above"); assert(Tok.getIdentifierInfo() && "Not an identifier?"); D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); - } else if (Tok.is(tok::l_paren)) { + goto PastIdentifier; + } + + if (Tok.is(tok::l_paren)) { // direct-declarator: '(' declarator ')' // direct-declarator: '(' attributes declarator ')' // Example: 'char (*X)' or 'int (*XX)(void)' @@ -2374,7 +2344,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { Diag(Tok, diag::err_expected_member_name_or_semi) << D.getDeclSpec().getSourceRange(); else if (getLang().CPlusPlus) - Diag(Tok, diag::err_expected_unqualified_id); + Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus; else Diag(Tok, diag::err_expected_ident_lparen); D.SetIdentifier(0, Tok.getLocation()); @@ -2623,6 +2593,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, SourceLocation DSStart = Tok.getLocation(); // Parse the declaration-specifiers. + // Just use the ParsingDeclaration "scope" of the declarator. DeclSpec DS; // If the caller parsed attributes for the first argument, add them now. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d381e3e..91f8686 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -323,6 +323,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SkipUntil(tok::semi); return DeclPtrTy(); } + // FIXME: what about conversion functions? } else if (Tok.is(tok::identifier)) { // Parse identifier. TargetName = Tok.getIdentifierInfo(); @@ -589,6 +590,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) Diag(Tok, diag::err_expected_ident); + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + // Parse the (optional) class name or simple-template-id. IdentifierInfo *Name = 0; SourceLocation NameLoc; @@ -596,6 +599,56 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); + + if (Tok.is(tok::less)) { + // The name was supposed to refer to a template, but didn't. + // Eat the template argument list and try to continue parsing this as + // a class (or template thereof). + TemplateArgList TemplateArgs; + TemplateArgIsTypeList TemplateArgIsType; + TemplateArgLocationList TemplateArgLocations; + SourceLocation LAngleLoc, RAngleLoc; + if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, + true, LAngleLoc, + TemplateArgs, TemplateArgIsType, + TemplateArgLocations, RAngleLoc)) { + // We couldn't parse the template argument list at all, so don't + // try to give any location information for the list. + LAngleLoc = RAngleLoc = SourceLocation(); + } + + Diag(NameLoc, diag::err_explicit_spec_non_template) + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + << (TagType == DeclSpec::TST_class? 0 + : TagType == DeclSpec::TST_struct? 1 + : 2) + << Name + << SourceRange(LAngleLoc, RAngleLoc); + + // Strip off the last template parameter list if it was empty, since + // we've removed its template argument list. + if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { + if (TemplateParams && TemplateParams->size() > 1) { + TemplateParams->pop_back(); + } else { + TemplateParams = 0; + const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind + = ParsedTemplateInfo::NonTemplate; + } + } else if (TemplateInfo.Kind + == ParsedTemplateInfo::ExplicitInstantiation) { + // Pretend this is just a forward declaration. + TemplateParams = 0; + const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind + = ParsedTemplateInfo::NonTemplate; + const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc + = SourceLocation(); + const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc + = SourceLocation(); + } + + + } } else if (Tok.is(tok::annot_template_id)) { TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); NameLoc = ConsumeToken(); @@ -660,7 +713,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Create the tag portion of the class or class template. Action::DeclResult TagOrTempResult = true; // invalid Action::TypeResult TypeResult = true; // invalid - TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; // FIXME: When TUK == TUK_Reference and we have a template-id, we need // to turn that template-id into a type. @@ -1047,7 +1099,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation DSStart = Tok.getLocation(); // decl-specifier-seq: // Parse the common declaration-specifiers piece. - DeclSpec DS; + ParsingDeclSpec DS(*this); ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class); Action::MultiTemplateParamsArg TemplateParams(Actions, @@ -1060,7 +1112,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - Declarator DeclaratorInfo(DS, Declarator::MemberContext); + ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); if (Tok.isNot(tok::colon)) { // Parse the first declarator. @@ -1179,6 +1231,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); } + DeclaratorInfo.complete(ThisDecl); + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. if (Tok.isNot(tok::comma)) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8be89a8..95a0e98 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -340,7 +340,18 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { // Eat the colon. ColonLoc = ConsumeToken(); } - + + if ((OpToken.is(tok::periodstar) || OpToken.is(tok::arrowstar)) + && Tok.is(tok::identifier)) { + CXXScopeSpec SS; + if (Actions.getTypeName(*Tok.getIdentifierInfo(), + Tok.getLocation(), CurScope, &SS)) { + const char *Opc = OpToken.is(tok::periodstar) ? "'.*'" : "'->*'"; + Diag(OpToken, diag::err_pointer_to_member_type) << Opc; + return ExprError(); + } + + } // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could @@ -612,36 +623,39 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParseCastExpression(isUnaryExpression, isAddressOfOperand); } - // Support 'Class.property' notation. - // We don't use isTokObjCMessageIdentifierReceiver(), since it allows - // 'super' (which is inappropriate here). - if (getLang().ObjC1 && - Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope) && - NextToken().is(tok::period)) { - IdentifierInfo &ReceiverName = *Tok.getIdentifierInfo(); - SourceLocation IdentLoc = ConsumeToken(); + // Consume the identifier so that we can see if it is followed by a '(' or + // '.'. + IdentifierInfo &II = *Tok.getIdentifierInfo(); + SourceLocation ILoc = ConsumeToken(); + + // Support 'Class.property' notation. We don't use + // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is + // inappropriate here). + if (getLang().ObjC1 && Tok.is(tok::period) && + Actions.getTypeName(II, ILoc, CurScope)) { SourceLocation DotLoc = ConsumeToken(); - + if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected_property_name); return ExprError(); } IdentifierInfo &PropertyName = *Tok.getIdentifierInfo(); SourceLocation PropertyLoc = ConsumeToken(); - - Res = Actions.ActOnClassPropertyRefExpr(ReceiverName, PropertyName, - IdentLoc, PropertyLoc); + + Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName, + ILoc, PropertyLoc); // These can be followed by postfix-expr pieces. return ParsePostfixExpressionSuffix(move(Res)); } - // Consume the identifier so that we can see if it is followed by a '('. + // Function designators are allowed to be undeclared (C99 6.5.1p2), so we // need to know whether or not this identifier is a function designator or // not. - IdentifierInfo &II = *Tok.getIdentifierInfo(); - SourceLocation L = ConsumeToken(); - Res = Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren)); + UnqualifiedId Name; + CXXScopeSpec ScopeSpec; + Name.setIdentifier(&II, ILoc); + Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name, + Tok.is(tok::l_paren), false); // These can be followed by postfix-expr pieces. return ParsePostfixExpressionSuffix(move(Res)); } @@ -954,110 +968,20 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) { ConsumeToken(); } - if (Tok.is(tok::identifier)) { - if (!LHS.isInvalid()) - LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc, - OpKind, Tok.getLocation(), - *Tok.getIdentifierInfo(), - ObjCImpDecl, &SS); - ConsumeToken(); - } else if (getLang().CPlusPlus && Tok.is(tok::tilde)) { - // We have a C++ pseudo-destructor or a destructor call, e.g., t.~T() - - // Consume the tilde. - ConsumeToken(); - - if (!Tok.is(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - return ExprError(); - } - - if (NextToken().is(tok::less)) { - // class-name: - // ~ simple-template-id - TemplateTy Template - = Actions.ActOnDependentTemplateName(SourceLocation(), - *Tok.getIdentifierInfo(), - Tok.getLocation(), - SS, - ObjectType); - if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS, - SourceLocation(), true)) - return ExprError(); - - assert(Tok.is(tok::annot_typename) && - "AnnotateTemplateIdToken didn't work?"); - if (!LHS.isInvalid()) - LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS), - OpLoc, OpKind, - Tok.getAnnotationRange(), - Tok.getAnnotationValue(), - SS, - NextToken().is(tok::l_paren)); - } else { - // class-name: - // ~ identifier - if (!LHS.isInvalid()) - LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS), - OpLoc, OpKind, - Tok.getLocation(), - Tok.getIdentifierInfo(), - SS, - NextToken().is(tok::l_paren)); - } - - // Consume the identifier or template-id token. - ConsumeToken(); - } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) { - // We have a reference to a member operator, e.g., t.operator int or - // t.operator+. - SourceLocation OperatorLoc = Tok.getLocation(); - - if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) { - if (!LHS.isInvalid()) - LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope, - move(LHS), OpLoc, - OpKind, - OperatorLoc, - Op, &SS); - // TryParseOperatorFunctionId already consumed our token, so - // don't bother - } else if (TypeTy *ConvType = ParseConversionFunctionId()) { - if (!LHS.isInvalid()) - LHS = Actions.ActOnConversionOperatorReferenceExpr(CurScope, - move(LHS), OpLoc, - OpKind, - OperatorLoc, - ConvType, &SS); - } else { - // Don't emit a diagnostic; ParseConversionFunctionId does it for us - return ExprError(); - } - } else if (getLang().CPlusPlus && Tok.is(tok::annot_template_id)) { - // We have a reference to a member template along with explicitly- - // specified template arguments, e.g., t.f<int>. - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - if (!LHS.isInvalid()) { - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), - TemplateId->NumArgs); - - LHS = Actions.ActOnMemberTemplateIdReferenceExpr(CurScope, move(LHS), - OpLoc, OpKind, SS, - TemplateTy::make(TemplateId->Template), - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), - TemplateId->RAngleLoc); - } - ConsumeToken(); - } else { - Diag(Tok, diag::err_expected_ident); + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/false, + ObjectType, + Name)) return ExprError(); - } + + if (!LHS.isInvalid()) + LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind, + SS, Name, ObjCImpDecl, + Tok.is(tok::l_paren)); + break; } case tok::plusplus: // postfix-expression: postfix-expression '++' diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index fa65156..a7ca0c5 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,8 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" +#include "llvm/Support/ErrorHandling.h" + using namespace clang; /// \brief Parse global scope or nested-name-specifier if present. @@ -107,31 +109,58 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, break; SourceLocation TemplateKWLoc = ConsumeToken(); - - if (Tok.isNot(tok::identifier)) { + + UnqualifiedId TemplateName; + if (Tok.is(tok::identifier)) { + TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + + // If the next token is not '<', we may have a stray 'template' keyword. + // Complain and suggest removing the template keyword, but otherwise + // allow parsing to continue. + if (NextToken().isNot(tok::less)) { + Diag(NextToken().getLocation(), + diag::err_less_after_template_name_in_nested_name_spec) + << Tok.getIdentifierInfo()->getName() + << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc)); + break; + } + + // Consume the identifier. + ConsumeToken(); + } else if (Tok.is(tok::kw_operator)) { + if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, + TemplateName)) + break; + + if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) { + Diag(TemplateName.getSourceRange().getBegin(), + diag::err_id_after_template_in_nested_name_spec) + << TemplateName.getSourceRange(); + break; + } else if (Tok.isNot(tok::less)) { + std::string OperatorName = "operator "; + OperatorName += getOperatorSpelling( + TemplateName.OperatorFunctionId.Operator); + Diag(Tok.getLocation(), + diag::err_less_after_template_name_in_nested_name_spec) + << OperatorName + << TemplateName.getSourceRange(); + break; + } + } else { Diag(Tok.getLocation(), diag::err_id_after_template_in_nested_name_spec) << SourceRange(TemplateKWLoc); break; } - if (NextToken().isNot(tok::less)) { - Diag(NextToken().getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << Tok.getIdentifierInfo()->getName() - << SourceRange(TemplateKWLoc, Tok.getLocation()); - break; - } - TemplateTy Template - = Actions.ActOnDependentTemplateName(TemplateKWLoc, - *Tok.getIdentifierInfo(), - Tok.getLocation(), SS, + = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName, ObjectType); if (!Template) break; if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, - &SS, TemplateKWLoc, false)) + &SS, TemplateName, TemplateKWLoc, false)) break; continue; @@ -218,9 +247,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // type-name '<' if (Next.is(tok::less)) { TemplateTy Template; - if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II, - Tok.getLocation(), - &SS, + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&II, Tok.getLocation()); + if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, + TemplateName, ObjectType, EnteringContext, Template)) { @@ -230,8 +260,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // because some clients (e.g., the parsing of class template // specializations) still want to see the original template-id // token. - if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), - false)) + ConsumeToken(); + if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + SourceLocation(), false)) break; continue; } @@ -251,25 +282,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, /// unqualified-id /// qualified-id /// -/// unqualified-id: -/// identifier -/// operator-function-id -/// conversion-function-id [TODO] -/// '~' class-name [TODO] -/// template-id -/// /// qualified-id: /// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id /// '::' identifier /// '::' operator-function-id /// '::' template-id /// -/// nested-name-specifier: -/// type-name '::' -/// namespace-name '::' -/// nested-name-specifier identifier '::' -/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] -/// /// NOTE: The standard specifies that, for qualified-id, the parser does not /// expect: /// @@ -307,69 +325,19 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { // CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); - - // unqualified-id: - // identifier - // operator-function-id - // conversion-function-id - // '~' class-name [TODO] - // template-id - // - switch (Tok.getKind()) { - default: - return ExprError(Diag(Tok, diag::err_expected_unqualified_id)); - - case tok::identifier: { - // Consume the identifier so that we can see if it is followed by a '('. - IdentifierInfo &II = *Tok.getIdentifierInfo(); - SourceLocation L = ConsumeToken(); - return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren), - &SS, isAddressOfOperand); - } - - case tok::kw_operator: { - SourceLocation OperatorLoc = Tok.getLocation(); - if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) - return Actions.ActOnCXXOperatorFunctionIdExpr( - CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS, - isAddressOfOperand); - if (TypeTy *Type = ParseConversionFunctionId()) - return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type, - Tok.is(tok::l_paren), SS, - isAddressOfOperand); - - // We already complained about a bad conversion-function-id, - // above. + + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/0, + Name)) return ExprError(); - } - - case tok::annot_template_id: { - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - assert((TemplateId->Kind == TNK_Function_template || - TemplateId->Kind == TNK_Dependent_template_name) && - "A template type name is not an ID expression"); - - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), - TemplateId->NumArgs); - - OwningExprResult Result - = Actions.ActOnTemplateIdExpr(SS, - TemplateTy::make(TemplateId->Template), - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), - TemplateId->RAngleLoc); - ConsumeToken(); // Consume the template-id token - return move(Result); - } - - } // switch. - - assert(0 && "The switch was supposed to take care everything."); + + return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren), + isAddressOfOperand); + } /// ParseCXXCasts - This handles the various ways to cast expressions to another @@ -761,6 +729,473 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { return false; } +/// \brief Finish parsing a C++ unqualified-id that is a template-id of +/// some form. +/// +/// This routine is invoked when a '<' is encountered after an identifier or +/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine +/// whether the unqualified-id is actually a template-id. This routine will +/// then parse the template arguments and form the appropriate template-id to +/// return to the caller. +/// +/// \param SS the nested-name-specifier that precedes this template-id, if +/// we're actually parsing a qualified-id. +/// +/// \param Name for constructor and destructor names, this is the actual +/// identifier that may be a template-name. +/// +/// \param NameLoc the location of the class-name in a constructor or +/// destructor. +/// +/// \param EnteringContext whether we're entering the scope of the +/// nested-name-specifier. +/// +/// \param ObjectType if this unqualified-id occurs within a member access +/// expression, the type of the base object whose member is being accessed. +/// +/// \param Id as input, describes the template-name or operator-function-id +/// that precedes the '<'. If template arguments were parsed successfully, +/// will be updated with the template-id. +/// +/// \returns true if a parse error occurred, false otherwise. +bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Id) { + assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id"); + + TemplateTy Template; + TemplateNameKind TNK = TNK_Non_template; + switch (Id.getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext, + Template); + break; + + case UnqualifiedId::IK_ConstructorName: { + UnqualifiedId TemplateName; + TemplateName.setIdentifier(Name, NameLoc); + TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, + EnteringContext, Template); + break; + } + + case UnqualifiedId::IK_DestructorName: { + UnqualifiedId TemplateName; + TemplateName.setIdentifier(Name, NameLoc); + if (ObjectType) { + Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, + TemplateName, ObjectType); + TNK = TNK_Dependent_template_name; + if (!Template.get()) + return true; + } else { + TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, + EnteringContext, Template); + + if (TNK == TNK_Non_template && Id.DestructorName == 0) { + // The identifier following the destructor did not refer to a template + // or to a type. Complain. + if (ObjectType) + Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) + << Name; + else + Diag(NameLoc, diag::err_destructor_class_name); + return true; + } + } + break; + } + + default: + return false; + } + + if (TNK == TNK_Non_template) + return false; + + // Parse the enclosed template argument list. + SourceLocation LAngleLoc, RAngleLoc; + TemplateArgList TemplateArgs; + TemplateArgIsTypeList TemplateArgIsType; + TemplateArgLocationList TemplateArgLocations; + if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, + &SS, true, LAngleLoc, + TemplateArgs, + TemplateArgIsType, + TemplateArgLocations, + RAngleLoc)) + return true; + + if (Id.getKind() == UnqualifiedId::IK_Identifier || + Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) { + // Form a parsed representation of the template-id to be stored in the + // UnqualifiedId. + TemplateIdAnnotation *TemplateId + = TemplateIdAnnotation::Allocate(TemplateArgs.size()); + + if (Id.getKind() == UnqualifiedId::IK_Identifier) { + TemplateId->Name = Id.Identifier; + TemplateId->Operator = OO_None; + TemplateId->TemplateNameLoc = Id.StartLocation; + } else { + TemplateId->Name = 0; + TemplateId->Operator = Id.OperatorFunctionId.Operator; + TemplateId->TemplateNameLoc = Id.StartLocation; + } + + TemplateId->Template = Template.getAs<void*>(); + TemplateId->Kind = TNK; + TemplateId->LAngleLoc = LAngleLoc; + TemplateId->RAngleLoc = RAngleLoc; + void **Args = TemplateId->getTemplateArgs(); + bool *ArgIsType = TemplateId->getTemplateArgIsType(); + SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations(); + for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); + Arg != ArgEnd; ++Arg) { + Args[Arg] = TemplateArgs[Arg]; + ArgIsType[Arg] = TemplateArgIsType[Arg]; + ArgLocs[Arg] = TemplateArgLocations[Arg]; + } + + Id.setTemplateId(TemplateId); + return false; + } + + // Bundle the template arguments together. + ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), + TemplateArgIsType.data(), + TemplateArgs.size()); + + // Constructor and destructor names. + Action::TypeResult Type + = Actions.ActOnTemplateIdType(Template, NameLoc, + LAngleLoc, TemplateArgsPtr, + &TemplateArgLocations[0], + RAngleLoc); + if (Type.isInvalid()) + return true; + + if (Id.getKind() == UnqualifiedId::IK_ConstructorName) + Id.setConstructorName(Type.get(), NameLoc, RAngleLoc); + else + Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc); + + return false; +} + +/// \brief Parse an operator-function-id or conversion-function-id as part +/// of a C++ unqualified-id. +/// +/// This routine is responsible only for parsing the operator-function-id or +/// conversion-function-id; it does not handle template arguments in any way. +/// +/// \code +/// operator-function-id: [C++ 13.5] +/// 'operator' operator +/// +/// operator: one of +/// new delete new[] delete[] +/// + - * / % ^ & | ~ +/// ! = < > += -= *= /= %= +/// ^= &= |= << >> >>= <<= == != +/// <= >= && || ++ -- , ->* -> +/// () [] +/// +/// 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] +/// \endcode +/// +/// \param The nested-name-specifier that preceded this unqualified-id. If +/// non-empty, then we are parsing the unqualified-id of a qualified-id. +/// +/// \param EnteringContext whether we are entering the scope of the +/// nested-name-specifier. +/// +/// \param ObjectType if this unqualified-id occurs within a member access +/// expression, the type of the base object whose member is being accessed. +/// +/// \param Result on a successful parse, contains the parsed unqualified-id. +/// +/// \returns true if parsing fails, false otherwise. +bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Result) { + assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); + + // Consume the 'operator' keyword. + SourceLocation KeywordLoc = ConsumeToken(); + + // Determine what kind of operator name we have. + unsigned SymbolIdx = 0; + SourceLocation SymbolLocations[3]; + OverloadedOperatorKind Op = OO_None; + switch (Tok.getKind()) { + case tok::kw_new: + case tok::kw_delete: { + bool isNew = Tok.getKind() == tok::kw_new; + // Consume the 'new' or 'delete'. + SymbolLocations[SymbolIdx++] = ConsumeToken(); + if (Tok.is(tok::l_square)) { + // Consume the '['. + SourceLocation LBracketLoc = ConsumeBracket(); + // Consume the ']'. + SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, + LBracketLoc); + if (RBracketLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LBracketLoc; + SymbolLocations[SymbolIdx++] = RBracketLoc; + Op = isNew? OO_Array_New : OO_Array_Delete; + } else { + Op = isNew? OO_New : OO_Delete; + } + break; + } + +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case tok::Token: \ + SymbolLocations[SymbolIdx++] = ConsumeToken(); \ + Op = OO_##Name; \ + break; +#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#include "clang/Basic/OperatorKinds.def" + + case tok::l_paren: { + // Consume the '('. + SourceLocation LParenLoc = ConsumeParen(); + // Consume the ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, + LParenLoc); + if (RParenLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LParenLoc; + SymbolLocations[SymbolIdx++] = RParenLoc; + Op = OO_Call; + break; + } + + case tok::l_square: { + // Consume the '['. + SourceLocation LBracketLoc = ConsumeBracket(); + // Consume the ']'. + SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, + LBracketLoc); + if (RBracketLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LBracketLoc; + SymbolLocations[SymbolIdx++] = RBracketLoc; + Op = OO_Subscript; + break; + } + + case tok::code_completion: { + // Code completion for the operator name. + Actions.CodeCompleteOperatorName(CurScope); + + // Consume the operator token. + ConsumeToken(); + + // Don't try to parse any further. + return true; + } + + default: + break; + } + + if (Op != OO_None) { + // We have parsed an operator-function-id. + Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations); + return false; + } + + // Parse a conversion-function-id. + // + // 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] + + // Parse the type-specifier-seq. + DeclSpec DS; + if (ParseCXXTypeSpecifierSeq(DS)) + return true; + + // Parse the conversion-declarator, which is merely a sequence of + // ptr-operators. + Declarator D(DS, Declarator::TypeNameContext); + ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); + + // Finish up the type. + Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D); + if (Ty.isInvalid()) + return true; + + // Note that this is a conversion-function-id. + Result.setConversionFunctionId(KeywordLoc, Ty.get(), + D.getSourceRange().getEnd()); + return false; +} + +/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the +/// name of an entity. +/// +/// \code +/// unqualified-id: [C++ expr.prim.general] +/// identifier +/// operator-function-id +/// conversion-function-id +/// [C++0x] literal-operator-id [TODO] +/// ~ class-name +/// template-id +/// +/// \endcode +/// +/// \param The nested-name-specifier that preceded this unqualified-id. If +/// non-empty, then we are parsing the unqualified-id of a qualified-id. +/// +/// \param EnteringContext whether we are entering the scope of the +/// nested-name-specifier. +/// +/// \param AllowDestructorName whether we allow parsing of a destructor name. +/// +/// \param AllowConstructorName whether we allow parsing a constructor name. +/// +/// \param ObjectType if this unqualified-id occurs within a member access +/// expression, the type of the base object whose member is being accessed. +/// +/// \param Result on a successful parse, contains the parsed unqualified-id. +/// +/// \returns true if parsing fails, false otherwise. +bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, + bool AllowDestructorName, + bool AllowConstructorName, + TypeTy *ObjectType, + UnqualifiedId &Result) { + // unqualified-id: + // identifier + // template-id (when it hasn't already been annotated) + if (Tok.is(tok::identifier)) { + // Consume the identifier. + IdentifierInfo *Id = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + + if (AllowConstructorName && + Actions.isCurrentClassName(*Id, CurScope, &SS)) { + // We have parsed a constructor name. + Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope, + &SS, false), + IdLoc, IdLoc); + } else { + // We have parsed an identifier. + Result.setIdentifier(Id, IdLoc); + } + + // If the next token is a '<', we may have a template. + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, + ObjectType, Result); + + return false; + } + + // unqualified-id: + // template-id (already parsed and annotated) + if (Tok.is(tok::annot_template_id)) { + // FIXME: Could this be a constructor name??? + + // We have already parsed a template-id; consume the annotation token as + // our unqualified-id. + Result.setTemplateId( + static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue())); + ConsumeToken(); + return false; + } + + // unqualified-id: + // operator-function-id + // conversion-function-id + if (Tok.is(tok::kw_operator)) { + if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result)) + return true; + + // If we have an operator-function-id and the next token is a '<', we may + // have a + // + // template-id: + // operator-function-id < template-argument-list[opt] > + if (Result.getKind() == UnqualifiedId::IK_OperatorFunctionId && + Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), + EnteringContext, ObjectType, + Result); + + return false; + } + + if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) { + // C++ [expr.unary.op]p10: + // There is an ambiguity in the unary-expression ~X(), where X is a + // class-name. The ambiguity is resolved in favor of treating ~ as a + // unary complement rather than treating ~X as referring to a destructor. + + // Parse the '~'. + SourceLocation TildeLoc = ConsumeToken(); + + // Parse the class-name. + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_destructor_class_name); + return true; + } + + // Parse the class-name (or template-name in a simple-template-id). + IdentifierInfo *ClassName = Tok.getIdentifierInfo(); + SourceLocation ClassNameLoc = ConsumeToken(); + + if (Tok.is(tok::less)) { + Result.setDestructorName(TildeLoc, 0, ClassNameLoc); + return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc, + EnteringContext, ObjectType, Result); + } + + // Note that this is a destructor name. + Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc, + CurScope, &SS); + if (!Ty) { + if (ObjectType) + Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) + << ClassName; + else + Diag(ClassNameLoc, diag::err_destructor_class_name); + return true; + } + + Result.setDestructorName(TildeLoc, Ty, ClassNameLoc); + return false; + } + + Diag(Tok, diag::err_expected_unqualified_id) + << getLang().CPlusPlus; + return true; +} + /// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded /// operator name (C++ [over.oper]). If successful, returns the /// predefined identifier that corresponds to that overloaded diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 2e0cd6d..b043dd99 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -305,51 +305,68 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, if (Tok.is(tok::l_paren)) ParseObjCPropertyAttribute(OCDS); + struct ObjCPropertyCallback : FieldCallback { + Parser &P; + DeclPtrTy IDecl; + llvm::SmallVectorImpl<DeclPtrTy> &Props; + ObjCDeclSpec &OCDS; + SourceLocation AtLoc; + tok::ObjCKeywordKind MethodImplKind; + + ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl, + llvm::SmallVectorImpl<DeclPtrTy> &Props, + ObjCDeclSpec &OCDS, SourceLocation AtLoc, + tok::ObjCKeywordKind MethodImplKind) : + P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc), + MethodImplKind(MethodImplKind) { + } + + DeclPtrTy invoke(FieldDeclarator &FD) { + if (FD.D.getIdentifier() == 0) { + P.Diag(AtLoc, diag::err_objc_property_requires_field_name) + << FD.D.getSourceRange(); + return DeclPtrTy(); + } + if (FD.BitfieldSize) { + P.Diag(AtLoc, diag::err_objc_property_bitfield) + << FD.D.getSourceRange(); + return DeclPtrTy(); + } + + // Install the property declarator into interfaceDecl. + IdentifierInfo *SelName = + OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); + + Selector GetterSel = + P.PP.getSelectorTable().getNullarySelector(SelName); + IdentifierInfo *SetterName = OCDS.getSetterName(); + Selector SetterSel; + if (SetterName) + SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName); + else + SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(), + P.PP.getSelectorTable(), + FD.D.getIdentifier()); + bool isOverridingProperty = false; + DeclPtrTy Property = + P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS, + GetterSel, SetterSel, IDecl, + &isOverridingProperty, + MethodImplKind); + if (!isOverridingProperty) + Props.push_back(Property); + + return Property; + } + } Callback(*this, interfaceDecl, allProperties, + OCDS, AtLoc, MethodImplKind); + // Parse all the comma separated declarators. DeclSpec DS; - llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; - ParseStructDeclaration(DS, FieldDeclarators); + ParseStructDeclaration(DS, Callback); ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", tok::at); - - // Convert them all to property declarations. - for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { - FieldDeclarator &FD = FieldDeclarators[i]; - if (FD.D.getIdentifier() == 0) { - Diag(AtLoc, diag::err_objc_property_requires_field_name) - << FD.D.getSourceRange(); - continue; - } - if (FD.BitfieldSize) { - Diag(AtLoc, diag::err_objc_property_bitfield) - << FD.D.getSourceRange(); - continue; - } - - // Install the property declarator into interfaceDecl. - IdentifierInfo *SelName = - OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); - - Selector GetterSel = - PP.getSelectorTable().getNullarySelector(SelName); - IdentifierInfo *SetterName = OCDS.getSetterName(); - Selector SetterSel; - if (SetterName) - SetterSel = PP.getSelectorTable().getSelector(1, &SetterName); - else - SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), - FD.D.getIdentifier()); - bool isOverridingProperty = false; - DeclPtrTy Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS, - GetterSel, SetterSel, - interfaceDecl, - &isOverridingProperty, - MethodImplKind); - if (!isOverridingProperty) - allProperties.push_back(Property); - } break; } } @@ -681,6 +698,8 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, DeclPtrTy IDecl, tok::ObjCKeywordKind MethodImplKind) { + ParsingDeclRAIIObject PD(*this); + // Parse the return type if present. TypeTy *ReturnType = 0; ObjCDeclSpec DSRet; @@ -707,10 +726,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, MethodAttrs = ParseAttributes(); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); - return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), + DeclPtrTy Result + = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, 0, CargNames, MethodAttrs, MethodImplKind); + PD.complete(Result); + return Result; } llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; @@ -783,10 +805,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, return DeclPtrTy(); Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); - return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), + DeclPtrTy Result + = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CargNames, MethodAttrs, MethodImplKind, isVariadic); + PD.complete(Result); + return Result; } /// objc-protocol-refs: @@ -858,7 +883,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls; - llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); @@ -893,21 +917,31 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, } } + struct ObjCIvarCallback : FieldCallback { + Parser &P; + DeclPtrTy IDecl; + tok::ObjCKeywordKind visibility; + llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls; + + ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V, + llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) : + P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { + } + + DeclPtrTy invoke(FieldDeclarator &FD) { + // Install the declarator into the interface decl. + DeclPtrTy Field + = P.Actions.ActOnIvar(P.CurScope, + FD.D.getDeclSpec().getSourceRange().getBegin(), + IDecl, FD.D, FD.BitfieldSize, visibility); + AllIvarDecls.push_back(Field); + return Field; + } + } Callback(*this, interfaceDecl, visibility, AllIvarDecls); + // Parse all the comma separated declarators. DeclSpec DS; - FieldDeclarators.clear(); - ParseStructDeclaration(DS, FieldDeclarators); - - // Convert them all to fields. - for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { - FieldDeclarator &FD = FieldDeclarators[i]; - // Install the declarator into interfaceDecl. - DeclPtrTy Field = Actions.ActOnIvar(CurScope, - DS.getSourceRange().getBegin(), - interfaceDecl, - FD.D, FD.BitfieldSize, visibility); - AllIvarDecls.push_back(Field); - } + ParseStructDeclaration(DS, Callback); if (Tok.is(tok::semi)) { ConsumeToken(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 272be2f..7637382 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -938,8 +938,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() { Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd, - false); + DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (Tok.is(tok::semi)) { // for (int x = 4; diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 8e63fb8..045acd8 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -101,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // (and retrieves the outer template parameter list from its // context). bool isSpecialization = true; + bool LastParamListWasEmpty = false; TemplateParameterLists ParamLists; TemplateParameterDepthCounter Depth(TemplateParameterDepth); do { @@ -140,13 +141,16 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, if (!TemplateParams.empty()) { isSpecialization = false; ++Depth; + } else { + LastParamListWasEmpty = true; } } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. return ParseSingleDeclarationAfterTemplate(Context, ParsedTemplateInfo(&ParamLists, - isSpecialization), + isSpecialization, + LastParamListWasEmpty), DeclEnd, AS); } @@ -186,16 +190,18 @@ Parser::ParseSingleDeclarationAfterTemplate( } // Parse the declaration specifiers. - DeclSpec DS; + ParsingDeclSpec DS(*this); ParseDeclarationSpecifiers(DS, TemplateInfo, AS); if (Tok.is(tok::semi)) { DeclEnd = ConsumeToken(); - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DS.complete(Decl); + return Decl; } // Parse the declarator. - Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); + ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context); ParseDeclarator(DeclaratorInfo); // Error parsing the declarator? if (!DeclaratorInfo.hasName()) { @@ -221,6 +227,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // Eat the semi colon after the declaration. ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); + DS.complete(ThisDecl); return ThisDecl; } @@ -668,22 +675,23 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, /// bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, const CXXScopeSpec *SS, + UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc, bool AllowTypeAnnotation) { assert(getLang().CPlusPlus && "Can only annotate template-ids in C++"); - assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) && + assert(Template && Tok.is(tok::less) && "Parser isn't at the beginning of a template-id"); // Consume the template-name. - IdentifierInfo *Name = Tok.getIdentifierInfo(); - SourceLocation TemplateNameLoc = ConsumeToken(); + SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin(); // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; TemplateArgIsTypeList TemplateArgIsType; TemplateArgLocationList TemplateArgLocations; - bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc, + bool Invalid = ParseTemplateIdAfterTemplateName(Template, + TemplateNameLoc, SS, false, LAngleLoc, TemplateArgs, TemplateArgIsType, @@ -732,7 +740,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Allocate(TemplateArgs.size()); TemplateId->TemplateNameLoc = TemplateNameLoc; - TemplateId->Name = Name; + if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) { + TemplateId->Name = TemplateName.Identifier; + TemplateId->Operator = OO_None; + } else { + TemplateId->Name = 0; + TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; + } TemplateId->Template = Template.getAs<void*>(); TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index bc737e9..335a6cf 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -526,7 +526,7 @@ bool Parser::isStartOfFunctionDefinition() { Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { // Parse the common declaration-specifiers piece. - DeclSpec DS; + ParsingDeclSpec DS(*this); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" @@ -534,6 +534,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { if (Tok.is(tok::semi)) { ConsumeToken(); DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -548,6 +549,9 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { SkipUntil(tok::semi); // FIXME: better skip? return DeclGroupPtrTy(); } + + DS.abort(); + const char *PrevSpec = 0; unsigned DiagID; if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID)) @@ -567,58 +571,12 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { if (Tok.is(tok::string_literal) && getLang().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { + DS.abort(); DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext); return Actions.ConvertDeclToDeclGroup(TheDecl); } - // Parse the first declarator. - Declarator DeclaratorInfo(DS, Declarator::FileContext); - ParseDeclarator(DeclaratorInfo); - // Error parsing the declarator? - if (!DeclaratorInfo.hasName()) { - // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, true, true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return DeclGroupPtrTy(); - } - - // If we have a declaration or declarator list, handle it. - if (isDeclarationAfterDeclarator()) { - // Parse the init-declarator-list for a normal declaration. - DeclGroupPtrTy DG = - ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); - // Eat the semi colon after the declaration. - ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); - return DG; - } - - if (DeclaratorInfo.isFunctionDeclarator() && - isStartOfFunctionDefinition()) { - if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { - Diag(Tok, diag::err_function_declared_typedef); - - if (Tok.is(tok::l_brace)) { - // This recovery skips the entire function body. It would be nice - // to simply call ParseFunctionDefinition() below, however Sema - // assumes the declarator represents a function, not a typedef. - ConsumeBrace(); - SkipUntil(tok::r_brace, true); - } else { - SkipUntil(tok::semi); - } - return DeclGroupPtrTy(); - } - DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo); - return Actions.ConvertDeclToDeclGroup(TheDecl); - } - - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return DeclGroupPtrTy(); + return ParseDeclGroup(DS, Declarator::FileContext, true); } /// ParseFunctionDefinition - We parsed and verified that the specified @@ -635,7 +593,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { /// [C++] function-definition: [C++ 8.4] /// decl-specifier-seq[opt] declarator function-try-block /// -Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D, +Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo) { const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); assert(FnTypeInfo.Kind == DeclaratorChunk::Function && @@ -687,6 +645,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D, D) : Actions.ActOnStartOfFunctionDef(CurScope, D); + // Break out of the ParsingDeclarator context before we parse the body. + D.complete(Res); + + // Break out of the ParsingDeclSpec context, too. This const_cast is + // safe because we're always the sole owner. + D.getMutableDeclSpec().abort(); + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res); @@ -981,17 +946,21 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { // If this is a template-id, annotate with a template-id or type token. if (NextToken().is(tok::less)) { TemplateTy Template; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); if (TemplateNameKind TNK - = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(), - Tok.getLocation(), &SS, + = Actions.isTemplateName(CurScope, SS, TemplateName, /*ObjectType=*/0, EnteringContext, - Template)) - if (AnnotateTemplateIdToken(Template, TNK, &SS)) { + Template)) { + // Consume the identifier. + ConsumeToken(); + if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) { // If an unrecoverable error occurred, we need to return true here, // because the token stream is in a damaged state. We may not return // a valid identifier. return Tok.isNot(tok::identifier); } + } } // The current token, which is either an identifier or a @@ -1065,3 +1034,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { PP.AnnotateCachedTokens(Tok); return true; } + +// Anchor the Parser::FieldCallback vtable to this translation unit. +// We use a spurious method instead of the destructor because +// destroying FieldCallbacks can actually be slightly +// performance-sensitive. +void Parser::FieldCallback::_anchor() { +} |