From 97144fc41a9419bf6d74fc9450e8ef3f6e11f7e0 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 2 Apr 2009 04:16:50 +0000 Subject: [PATCH] fix a FIXME, providing accurate source range info for DeclStmt's. The end of the range is now the ';' location. For something like this: $ cat t2.c #define bool int void f(int x, int y) { bool b = !x && y; } We used to produce: $ clang-cc t2.c -ast-dump typedef char *__builtin_va_list; void f(int x, int y) (CompoundStmt 0x2201f10 (DeclStmt 0x2201ef0 <---- 0x2201a20 "int b = (BinaryOperator 0x2201ed0 'int' '&&' (UnaryOperator 0x2201e90 'int' prefix '!' (DeclRefExpr 0x2201c90 'int' ParmVar='x' 0x2201a50)) (DeclRefExpr 0x2201eb0 'int' ParmVar='y' 0x2201e10))") Now we produce: $ clang-cc t2.c -ast-dump typedef char *__builtin_va_list; void f(int x, int y) (CompoundStmt 0x2201f10 (DeclStmt 0x2201ef0 <------ 0x2201a20 "int b = (BinaryOperator 0x2201ed0 'int' '&&' (UnaryOperator 0x2201e90 'int' prefix '!' (DeclRefExpr 0x2201c90 'int' ParmVar='x' 0x2201a50)) (DeclRefExpr 0x2201eb0 'int' ParmVar='y' 0x2201e10))") git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68288 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 20 ++++++++++++------- lib/Parse/ParseDecl.cpp | 19 +++++++++++------- lib/Parse/ParseDeclCXX.cpp | 38 ++++++++++++++++++++++++------------ lib/Parse/ParseStmt.cpp | 21 ++++++++++---------- lib/Parse/ParseTemplate.cpp | 4 ++++ lib/Parse/Parser.cpp | 5 ++++- 6 files changed, 68 insertions(+), 39 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 3969cf4765..85f6d50ebb 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -809,8 +809,9 @@ private: //===--------------------------------------------------------------------===// // C99 6.7: Declarations. - DeclGroupPtrTy ParseDeclaration(unsigned Context); + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd); DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, + SourceLocation &DeclEnd, bool RequireSemi = true); DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); @@ -994,14 +995,18 @@ private: //===--------------------------------------------------------------------===// // C++ 7: Declarations [dcl.dcl] - DeclPtrTy ParseNamespace(unsigned Context); + DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); DeclPtrTy ParseLinkage(unsigned Context); - DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context); - DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc); - DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc); - DeclPtrTy ParseStaticAssertDeclaration(); + DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, + SourceLocation &DeclEnd); + DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd); + DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd); + DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd); DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc, - SourceLocation AliasLoc, IdentifierInfo *Alias); + SourceLocation AliasLoc, IdentifierInfo *Alias, + SourceLocation &DeclEnd); //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. @@ -1035,6 +1040,7 @@ private: // C++ 14.1: Template Parameters [temp.param] DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context, + SourceLocation &DeclEnd, AccessSpecifier AS=AS_none); bool ParseTemplateParameters(unsigned Depth, TemplateParameterList &TemplateParams, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 104ca0336b..1f8d473891 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -215,7 +215,8 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. -/// 'Context' should be a Declarator::TheContext value. +/// 'Context' should be a Declarator::TheContext value. This returns the +/// location of the semicolon in DeclEnd. /// /// declaration: [C99 6.7] /// block-declaration -> @@ -228,24 +229,25 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// [C++0x] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) { +Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, + SourceLocation &DeclEnd) { DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::kw_export: case tok::kw_template: - SingleDecl = ParseTemplateDeclarationOrSpecialization(Context); + SingleDecl = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd); break; case tok::kw_namespace: - SingleDecl = ParseNamespace(Context); + SingleDecl = ParseNamespace(Context, DeclEnd); break; case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd); break; case tok::kw_static_assert: - SingleDecl = ParseStaticAssertDeclaration(); + SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context); + return ParseSimpleDeclaration(Context, DeclEnd); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -261,6 +263,7 @@ 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) { // Parse the common declaration-specifiers piece. DeclSpec DS; @@ -280,6 +283,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, DeclGroupPtrTy DG = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + DeclEnd = Tok.getLocation(); + // If the client wants to check what comes after the declaration, just return // immediately without checking anything! if (!RequireSemi) return DG; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 1cf4a8fe5f..bef1fb71d4 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -42,7 +42,8 @@ using namespace clang; /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] /// 'namespace' identifier '=' qualified-namespace-specifier ';' /// -Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context) { +Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context, + SourceLocation &DeclEnd) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. @@ -62,7 +63,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context) { if (Tok.is(tok::equal)) // FIXME: Verify no attributes were present. - return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident); + return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); if (Tok.isNot(tok::l_brace)) { Diag(Tok, Ident ? diag::err_expected_lbrace : @@ -88,9 +89,10 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context) { // Leave the namespace scope. NamespaceScope.Exit(); - SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); - Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace); + SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); + Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); + DeclEnd = RBraceLoc; return NamespcDecl; } @@ -99,7 +101,8 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context) { /// Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation AliasLoc, - IdentifierInfo *Alias) { + IdentifierInfo *Alias, + SourceLocation &DeclEnd) { assert(Tok.is(tok::equal) && "Not equal token"); ConsumeToken(); // eat the '='. @@ -120,6 +123,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation IdentLoc = ConsumeToken(); // Eat the ';'. + DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "namespace name", tok::semi); @@ -169,7 +173,8 @@ Parser::DeclPtrTy Parser::ParseLinkage(unsigned Context) { /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or /// using-directive. Assumes that current token is 'using'. -Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context) { +Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, + SourceLocation &DeclEnd) { assert(Tok.is(tok::kw_using) && "Not using token"); // Eat 'using'. @@ -177,10 +182,10 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context) { if (Tok.is(tok::kw_namespace)) // Next token after 'using' is 'namespace' so it must be using-directive - return ParseUsingDirective(Context, UsingLoc); + return ParseUsingDirective(Context, UsingLoc, DeclEnd); // Otherwise, it must be using-declaration. - return ParseUsingDeclaration(Context, UsingLoc); + return ParseUsingDeclaration(Context, UsingLoc, DeclEnd); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -194,7 +199,8 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context) { /// namespace-name attributes[opt] ; /// Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, - SourceLocation UsingLoc) { + SourceLocation UsingLoc, + SourceLocation &DeclEnd) { assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token"); // Eat 'namespace'. @@ -226,6 +232,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, AttrList = ParseAttributes(); // Eat ';'. + DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, AttrList ? "attributes list" : "namespace name", tok::semi); @@ -242,7 +249,8 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, /// 'using' :: unqualified-id [TODO] /// Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, - SourceLocation UsingLoc) { + SourceLocation UsingLoc, + SourceLocation &DeclEnd) { assert(false && "Not implemented"); // FIXME: Implement parsing. return DeclPtrTy(); @@ -253,7 +261,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, /// static_assert-declaration: /// static_assert ( constant-expression , string-literal ) ; /// -Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration() { +Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration"); SourceLocation StaticAssertLoc = ConsumeToken(); @@ -285,6 +293,7 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration() { MatchRHSPunctuation(tok::r_paren, LParenLoc); + DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert); return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr), @@ -668,12 +677,15 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // static_assert-declaration if (Tok.is(tok::kw_static_assert)) { - ParseStaticAssertDeclaration(); + SourceLocation DeclEnd; + ParseStaticAssertDeclaration(DeclEnd); return; } if (Tok.is(tok::kw_template)) { - ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, AS); + SourceLocation DeclEnd; + ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, DeclEnd, + AS); return; } diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b11ffbe82e..b87ede9388 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -100,10 +100,9 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) { default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { - SourceLocation DeclStart = Tok.getLocation(); - DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext); - // FIXME: Pass in the right location for the end of the declstmt. - return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart); + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; + DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd); + return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); } if (Tok.is(tok::r_brace)) { @@ -442,11 +441,10 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // If this is the start of a declaration, parse it as such. if (isDeclarationStatement()) { - // FIXME: Save the __extension__ on the decl as a node somehow. - SourceLocation DeclStart = Tok.getLocation(); - DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext); - // FIXME: Pass in the right location for the end of the declstmt. - R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart); + // FIXME: Save the __extension__ on the decl as a node somehow? + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; + DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext,DeclEnd); + R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd); } else { // Otherwise this was a unary __extension__ marker. OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc)); @@ -911,8 +909,9 @@ Parser::OwningStmtResult Parser::ParseForStatement() { if (!C99orCXX) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); - SourceLocation DeclStart = Tok.getLocation(); - DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, false); + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; + DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd, + false); 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 0f9bcd2219..d38df93ace 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -35,6 +35,7 @@ using namespace clang; /// 'template' '<' '>' declaration Parser::DeclPtrTy Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, + SourceLocation &DeclEnd, AccessSpecifier AS) { assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) && "Token does not start a template declaration."); @@ -99,6 +100,9 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // FIXME: Converting DeclGroupPtr to DeclPtr like this is an insanely gruesome // hack, will bring up on cfe-dev. DeclGroupPtrTy DG = ParseDeclarationOrFunctionDefinition(&ParamLists, AS); + // FIXME: Should be ';' location not the token after it. Resolve with above + // fixmes. + DeclEnd = Tok.getLocation(); return DeclPtrTy::make(DG.get()); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 495d5e51dd..a245ac2156 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -423,7 +423,10 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() { case tok::kw_export: // As in 'export template' case tok::kw_static_assert: // A function definition cannot start with a these keywords. - return ParseDeclaration(Declarator::FileContext); + { + SourceLocation DeclEnd; + return ParseDeclaration(Declarator::FileContext, DeclEnd); + } default: // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); -- 2.40.0