From 2e23209df1652630ed9a7ca8cb8e71719560f26e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 13 Mar 2008 06:29:04 +0000 Subject: [PATCH] improve DeclStmt to be able to store SourceRange info correctly. Set the start of DeclStmt range. Right now the end is meaningless though. llvm-svn: 48330 --- clang/AST/StmtSerialization.cpp | 6 +++++- clang/Parse/ParseDecl.cpp | 6 +++--- clang/Parse/ParseObjc.cpp | 8 +++++--- clang/Parse/ParseStmt.cpp | 20 ++++++++++++++++---- clang/Sema/Sema.h | 3 ++- clang/Sema/SemaStmt.cpp | 14 +++++++------- clang/include/clang/AST/Stmt.h | 10 ++++++++-- clang/include/clang/Parse/Action.h | 3 ++- clang/include/clang/Parse/DeclSpec.h | 9 ++++++--- 9 files changed, 54 insertions(+), 25 deletions(-) diff --git a/clang/AST/StmtSerialization.cpp b/clang/AST/StmtSerialization.cpp index 5f1ab6207200..433e8e270264 100644 --- a/clang/AST/StmtSerialization.cpp +++ b/clang/AST/StmtSerialization.cpp @@ -456,6 +456,8 @@ ContinueStmt* ContinueStmt::CreateImpl(Deserializer& D) { void DeclStmt::EmitImpl(Serializer& S) const { // FIXME: special handling for struct decls. S.EmitOwnedPtr(getDecl()); + S.Emit(StartLoc); + S.Emit(EndLoc); } void DeclRefExpr::EmitImpl(Serializer& S) const { @@ -505,7 +507,9 @@ DeclRefExpr* DeclRefExpr::CreateImpl(Deserializer& D) { DeclStmt* DeclStmt::CreateImpl(Deserializer& D) { ScopedDecl* decl = cast(D.ReadOwnedPtr()); - return new DeclStmt(decl); + SourceLocation StartLoc = SourceLocation::ReadVal(D); + SourceLocation EndLoc = SourceLocation::ReadVal(D); + return new DeclStmt(decl, StartLoc, EndLoc); } void DefaultStmt::EmitImpl(Serializer& S) const { diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp index 8b8d64535156..7d15e984ee62 100644 --- a/clang/Parse/ParseDecl.cpp +++ b/clang/Parse/ParseDecl.cpp @@ -388,7 +388,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { /// [C99] 'inline' /// void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { - DS.Range.setBegin(Tok.getLocation()); + DS.SetRangeStart(Tok.getLocation()); while (1) { int isInvalid = false; const char *PrevSpec = 0; @@ -409,7 +409,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { if (isInvalid) break; // FIXME: restrict this to "id" and ObjC classnames. - DS.Range.setEnd(Tok.getLocation()); + DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); // The identifier if (Tok.is(tok::less)) { SourceLocation endProtoLoc; @@ -555,7 +555,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { else // extwarn. Diag(Tok, diag::ext_duplicate_declspec, PrevSpec); } - DS.Range.setEnd(Tok.getLocation()); + DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); } } diff --git a/clang/Parse/ParseObjc.cpp b/clang/Parse/ParseObjc.cpp index 7f33ffd4c8a2..77d2adbd320b 100644 --- a/clang/Parse/ParseObjc.cpp +++ b/clang/Parse/ParseObjc.cpp @@ -1186,9 +1186,11 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { // FIXME: Is BlockContext right? Declarator DeclaratorInfo(DS, Declarator::BlockContext); ParseDeclarator(DeclaratorInfo); - DeclTy * aBlockVarDecl = Actions.ActOnDeclarator(CurScope, - DeclaratorInfo, 0); - StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl); + DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope, + DeclaratorInfo, 0); + StmtResult stmtResult = + Actions.ActOnDeclStmt(aBlockVarDecl, DS.getSourceRange().getBegin(), + DeclaratorInfo.getSourceRange().getEnd()); FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val; } else ConsumeToken(); // consume '...' diff --git a/clang/Parse/ParseStmt.cpp b/clang/Parse/ParseStmt.cpp index 389d5d4a54db..160701ee9c78 100644 --- a/clang/Parse/ParseStmt.cpp +++ b/clang/Parse/ParseStmt.cpp @@ -93,7 +93,10 @@ Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) { default: if (!OnlyStatement && isDeclarationSpecifier()) { - return Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext)); + SourceLocation DeclStart = Tok.getLocation(); + DeclTy *Res = ParseDeclaration(Declarator::BlockContext); + // FIXME: Pass in the right location for the end of the declstmt. + return Actions.ActOnDeclStmt(Res, DeclStart, SourceLocation()); } else if (Tok.is(tok::r_brace)) { Diag(Tok, diag::err_expected_statement); return true; @@ -255,7 +258,9 @@ Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) { ParseDeclarator(DeclaratorInfo); DeclTy *Decl = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); - return Decl ? Actions.ActOnDeclStmt(Decl) : 0; + if (!Decl) return 0; + return Actions.ActOnDeclStmt(Decl, DS.getSourceRange().getBegin(), + DeclaratorInfo.getSourceRange().getEnd()); } // Otherwise, this is an expression. Seed it with II and parse it. @@ -430,7 +435,10 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (isDeclarationSpecifier()) { // FIXME: Save the __extension__ on the decl as a node somehow. // FIXME: disable extwarns. - R = Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext)); + SourceLocation DeclStart = Tok.getLocation(); + DeclTy *Res = ParseDeclaration(Declarator::BlockContext); + // FIXME: Pass in the right location for the end of the declstmt. + R = Actions.ActOnDeclStmt(Res, DeclStart, SourceLocation()); } else { // Otherwise this was a unary __extension__ marker. Parse the // subexpression and add the __extension__ unary op. @@ -743,8 +751,12 @@ Parser::StmtResult Parser::ParseForStatement() { // Parse declaration, which eats the ';'. if (!getLang().C99) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); + + SourceLocation DeclStart = Tok.getLocation(); DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext); - StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl); + // FIXME: Pass in the right location for the end of the declstmt. + StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart, + SourceLocation()); FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val; if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 2fe54de5d02c..fc81781911c9 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -339,7 +339,8 @@ public: virtual StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, StmtTy **Elts, unsigned NumElts, bool isStmtExpr); - virtual StmtResult ActOnDeclStmt(DeclTy *Decl); + virtual StmtResult ActOnDeclStmt(DeclTy *Decl, SourceLocation StartLoc, + SourceLocation EndLoc); virtual StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprTy *LHSVal, SourceLocation DotDotDotLoc, ExprTy *RHSVal, SourceLocation ColonLoc, StmtTy *SubStmt); diff --git a/clang/Sema/SemaStmt.cpp b/clang/Sema/SemaStmt.cpp index fe62c8ab0695..14b2fdf7d0e4 100644 --- a/clang/Sema/SemaStmt.cpp +++ b/clang/Sema/SemaStmt.cpp @@ -33,13 +33,13 @@ Sema::StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) { return new NullStmt(SemiLoc); } -Sema::StmtResult Sema::ActOnDeclStmt(DeclTy *decl) { - if (decl) { - ScopedDecl *SD = dyn_cast(static_cast(decl)); - assert(SD && "Sema::ActOnDeclStmt(): expected ScopedDecl"); - return new DeclStmt(SD); - } else - return true; // error +Sema::StmtResult Sema::ActOnDeclStmt(DeclTy *decl, SourceLocation StartLoc, + SourceLocation EndLoc) { + if (decl == 0) + return true; + + ScopedDecl *SD = cast(static_cast(decl)); + return new DeclStmt(SD, StartLoc, EndLoc); } Action::StmtResult diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 662fbac17468..12251f4eccea 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -132,13 +132,19 @@ public: /// class DeclStmt : public Stmt { ScopedDecl *TheDecl; + SourceLocation StartLoc, EndLoc; public: - DeclStmt(ScopedDecl *D) : Stmt(DeclStmtClass), TheDecl(D) {} + DeclStmt(ScopedDecl *D, SourceLocation startLoc, SourceLocation endLoc) + : Stmt(DeclStmtClass), TheDecl(D), StartLoc(startLoc), EndLoc(endLoc) {} const ScopedDecl *getDecl() const { return TheDecl; } ScopedDecl *getDecl() { return TheDecl; } - virtual SourceRange getSourceRange() const { return SourceRange(); } + SourceLocation getStartLoc() const { return StartLoc; } + SourceLocation getEndLoc() const { return EndLoc; } + virtual SourceRange getSourceRange() const { + return SourceRange(StartLoc, EndLoc); + } static bool classof(const Stmt *T) { return T->getStmtClass() == DeclStmtClass; diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 63d9a72c9096..abf34e205c90 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -220,7 +220,8 @@ public: bool isStmtExpr) { return 0; } - virtual StmtResult ActOnDeclStmt(DeclTy *Decl) { + virtual StmtResult ActOnDeclStmt(DeclTy *Decl, SourceLocation StartLoc, + SourceLocation EndLoc) { return 0; } diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index 68a019a4a30b..182b54c12834 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -28,9 +28,6 @@ namespace clang { /// type-qualifiers, and function-specifiers. class DeclSpec { public: - SourceRange Range; - const SourceRange &getSourceRange() const { return Range; } - // storage-class-specifier enum SCS { SCS_unspecified, @@ -130,6 +127,8 @@ private: // SourceLocation info. These are null if the item wasn't specified or if // the setting was synthesized. + SourceRange Range; + SourceLocation StorageClassSpecLoc, SCS_threadLoc; SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; @@ -181,6 +180,7 @@ public: TST getTypeSpecType() const { return (TST)TypeSpecType; } void *getTypeRep() const { return TypeRep; } + const SourceRange &getSourceRange() const { return Range; } SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } @@ -222,6 +222,9 @@ public: /// unsigned getParsedSpecifiers() const; + void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } + void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } + /// These methods set the specified attribute of the DeclSpec, but return true /// and ignore the request if invalid (e.g. "extern" then "auto" is /// specified). The name of the previous specifier is returned in prevspec.