From ab197baec16bacade82325fb274cf6b992ac5d8a Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 9 Feb 2009 18:23:29 +0000 Subject: [PATCH] Implement Declarator::getSourceRange(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64151 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/DeclSpec.h | 96 +++++++++++++++----- include/clang/Parse/Parser.h | 21 +++-- lib/Parse/AttributeList.cpp | 2 +- lib/Parse/ParseDecl.cpp | 158 +++++++++++++++++++++------------ lib/Parse/ParseDeclCXX.cpp | 20 +++-- lib/Parse/ParseExpr.cpp | 15 +++- lib/Parse/ParseExprCXX.cpp | 55 +++++++++--- lib/Parse/Parser.cpp | 19 ++-- lib/Sema/SemaDecl.cpp | 5 +- 9 files changed, 273 insertions(+), 118 deletions(-) diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 83c0d6179f..008c161ac8 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -717,7 +717,8 @@ private: CXXScopeSpec SS; IdentifierInfo *Identifier; SourceLocation IdentifierLoc; - + SourceRange Range; + /// Context - Where we are parsing this declarator. /// TheContext Context; @@ -731,7 +732,7 @@ private: /// DeclTypeInfo.back() will be the least closely bound. llvm::SmallVector DeclTypeInfo; - // InvalidType - Set by Sema::GetTypeForDeclarator(). + /// InvalidType - Set by Sema::GetTypeForDeclarator(). bool InvalidType : 1; /// GroupingParens - Set by Parser::ParseParenDeclarator(). @@ -757,13 +758,15 @@ private: /// InlineParams - This is a local array used for the first function decl /// chunk to avoid going to the heap for the common case when we have one /// function chunk in the declarator. - friend class DeclaratorChunk; DeclaratorChunk::ParamInfo InlineParams[16]; bool InlineParamsUsed; - + + friend class DeclaratorChunk; + public: Declarator(const DeclSpec &ds, TheContext C) - : DS(ds), Identifier(0), Context(C), Kind(DK_Abstract), + : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C), + Kind(DK_Abstract), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), GroupingParens(false), AttrList(0), AsmLabel(0), Type(0), InlineParamsUsed(false) { @@ -792,14 +795,38 @@ public: TheContext getContext() const { return Context; } DeclaratorKind getKind() const { return Kind; } - // getSourceRange - FIXME: This should be implemented. - const SourceRange getSourceRange() const { return SourceRange(); } - + /// getSourceRange - Get the source range that spans this declarator. + const SourceRange &getSourceRange() const { return Range; } + + void SetSourceRange(SourceRange R) { Range = R; } + /// SetRangeBegin - Set the start of the source range to Loc, unless it's + /// invalid. + void SetRangeBegin(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setBegin(Loc); + } + /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid. + void SetRangeEnd(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setEnd(Loc); + } + /// ExtendWithDeclSpec - Extend the declarator source range to include the + /// given declspec, unless its location is invalid. Adopts the range start if + /// the current range start is invalid. + void ExtendWithDeclSpec(const DeclSpec &DS) { + const SourceRange &SR = DS.getSourceRange(); + if (Range.getBegin().isInvalid()) + Range.setBegin(SR.getBegin()); + if (!SR.getEnd().isInvalid()) + Range.setEnd(SR.getEnd()); + } + /// clear - Reset the contents of this Declarator. void clear() { SS.clear(); Identifier = 0; IdentifierLoc = SourceLocation(); + Range = DS.getSourceRange(); Kind = DK_Abstract; for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) @@ -856,45 +883,66 @@ public: Kind = DK_Normal; else Kind = DK_Abstract; + SetRangeEnd(Loc); } /// setConstructor - Set this declarator to be a C++ constructor - /// declarator. + /// declarator. Also extends the range. void setConstructor(Action::TypeTy *Ty, SourceLocation Loc) { IdentifierLoc = Loc; Kind = DK_Constructor; Type = Ty; + SetRangeEnd(Loc); } /// setDestructor - Set this declarator to be a C++ destructor - /// declarator. - void setDestructor(Action::TypeTy *Ty, SourceLocation Loc) { + /// declarator. Also extends the range to End, which should be the identifier + /// token. + void setDestructor(Action::TypeTy *Ty, SourceLocation Loc, + SourceLocation EndLoc) + { IdentifierLoc = Loc; Kind = DK_Destructor; Type = Ty; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); } - // setConversionFunction - Set this declarator to be a C++ - // conversion function declarator (e.g., @c operator int const *). - void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) { + /// setConversionFunction - Set this declarator to be a C++ + /// conversion function declarator (e.g., @c operator int const *). + /// Also extends the range to EndLoc, which should be the last token of the + /// type name. + void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc, + SourceLocation EndLoc) { Identifier = 0; IdentifierLoc = Loc; Kind = DK_Conversion; Type = Ty; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); } - // setOverloadedOperator - Set this declaration to be a C++ - // overloaded operator declarator (e.g., @c operator+). - void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc) { + /// setOverloadedOperator - Set this declaration to be a C++ + /// overloaded operator declarator (e.g., @c operator+). + /// Also extends the range to EndLoc, which should be the last token of the + /// operator. + void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc, + SourceLocation EndLoc) { IdentifierLoc = Loc; Kind = DK_Operator; OperatorKind = Op; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); } - - void AddTypeInfo(const DeclaratorChunk &TI) { + + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to + /// EndLoc, which should be the last token of the chunk. + void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); } - + /// getNumTypeObjects() - Return the number of types applied to this /// declarator. unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } @@ -923,13 +971,17 @@ public: /// short int x, __attribute__((aligned(16)) var /// __attribute__((common,deprecated)); /// - void AddAttributes(AttributeList *alist) { + /// Also extends the range of the declarator. + void AddAttributes(AttributeList *alist, SourceLocation LastLoc) { if (!alist) return; // we parsed __attribute__(()) or had a syntax error - + if (AttrList) alist->addAttributeList(AttrList); AttrList = alist; + + if (!LastLoc.isInvalid()) + SetRangeEnd(LastLoc); } const AttributeList *getAttributes() const { return AttrList; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index eec08cc0a2..da29208ccb 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -22,10 +22,6 @@ namespace clang { class AttributeList; - class DeclSpec; - class Declarator; - class FieldDeclarator; - class ObjCDeclSpec; class PragmaHandler; class Scope; class DiagnosticBuilder; @@ -511,7 +507,9 @@ private: TemplateParameterLists *TemplateParams = 0); DeclTy *ParseFunctionDefinition(Declarator &D); void ParseKNRParamDeclarations(Declarator &D); - OwningExprResult ParseSimpleAsm(); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the simple-asm. + OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); OwningExprResult ParseAsmStringLiteral(); // Objective-C External Declarations @@ -634,7 +632,8 @@ private: //===--------------------------------------------------------------------===// // C++ 15: C++ Throw Expression OwningExprResult ParseThrowExpression(); - bool ParseExceptionSpecification(); + // EndLoc is filled with the location of the last token of the specification. + bool ParseExceptionSpecification(SourceLocation &EndLoc); //===--------------------------------------------------------------------===// // C++ 2.13.5: C++ Boolean Literals @@ -899,7 +898,9 @@ private: TypeTy *ParseTypeName(); void ParseBlockId(); - AttributeList *ParseAttributes(); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the attribute list. + AttributeList *ParseAttributes(SourceLocation *EndLoc = 0); void FuzzyParseMicrosoftDeclSpec(); void ParseTypeofSpecifier(DeclSpec &DS); @@ -967,8 +968,10 @@ private: //===--------------------------------------------------------------------===// // C++ 13.5: Overloaded operators [over.oper] - OverloadedOperatorKind TryParseOperatorFunctionId(); - TypeTy *ParseConversionFunctionId(); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the ID. + OverloadedOperatorKind TryParseOperatorFunctionId(SourceLocation *EndLoc = 0); + TypeTy *ParseConversionFunctionId(SourceLocation *EndLoc = 0); //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 477d6e363d..eb0527dcf9 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -16,7 +16,7 @@ using namespace clang; AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc, IdentifierInfo *pName, SourceLocation pLoc, - Action::ExprTy **elist, unsigned numargs, + Action::ExprTy **elist, unsigned numargs, AttributeList *n) : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc), NumArgs(numargs), Next(n) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d646ad4cc0..73a09ee39c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -76,7 +76,7 @@ Parser::TypeTy *Parser::ParseTypeName() { /// attributes are very simple in practice. Until we find a bug, I don't see /// a pressing need to implement the 2 token lookahead. -AttributeList *Parser::ParseAttributes() { +AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { assert(Tok.is(tok::kw___attribute) && "Not an attribute list!"); AttributeList *CurrAttr = 0; @@ -185,9 +185,13 @@ AttributeList *Parser::ParseAttributes() { } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) - SkipUntil(tok::r_paren, false); - if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); + SourceLocation Loc = Tok.getLocation();; + if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { + SkipUntil(tok::r_paren, false); + } + if (EndLoc) + *EndLoc = Loc; } return CurrAttr; } @@ -288,18 +292,23 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { while (1) { // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { - OwningExprResult AsmLabel(ParseSimpleAsm()); + SourceLocation Loc; + OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi); return 0; } - + D.setAsmLabel(AsmLabel.release()); + D.SetRangeEnd(Loc); } // If attributes are present, parse them. - if (Tok.is(tok::kw___attribute)) - D.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + D.AddAttributes(AttrList, Loc); + } // Inform the current actions module that we just parsed this declarator. LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup); @@ -356,8 +365,11 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // short __attribute__((common)) var; -> declspec // short var __attribute__((common)); -> declarator // short x, __attribute__((common)) var; -> declarator - if (Tok.is(tok::kw___attribute)) - D.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + D.AddAttributes(AttrList, Loc); + } ParseDeclarator(D); } @@ -1020,25 +1032,31 @@ ParseStructDeclaration(DeclSpec &DS, else DeclaratorInfo.BitfieldSize = Res.release(); } - + // If attributes exist after the declarator, parse them. - if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.D.AddAttributes(ParseAttributes()); - + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.D.AddAttributes(AttrList, Loc); + } + // 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)) return; - + // 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)) - Fields.back().D.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + Fields.back().D.AddAttributes(AttrList, Loc); + } } } @@ -1584,8 +1602,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } SourceLocation Loc = ConsumeToken(); + D.SetRangeEnd(Loc); DeclSpec DS; ParseTypeQualifierListOpt(DS); + D.ExtendWithDeclSpec(DS); // Recurse to parse whatever is left. ParseDeclaratorInternal(D, DirectDeclParser); @@ -1593,7 +1613,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - Loc,DS.TakeAttributes())); + Loc, DS.TakeAttributes()), + /* Don't replace range end. */SourceLocation()); return; } } @@ -1608,24 +1629,28 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } // Otherwise, '*' -> pointer, '^' -> block, '&' -> reference. - SourceLocation Loc = ConsumeToken(); // Eat the * or &. + SourceLocation Loc = ConsumeToken(); // Eat the *, ^ or &. + D.SetRangeEnd(Loc); if (Kind == tok::star || (Kind == tok::caret && getLang().Blocks)) { // Is a pointer. DeclSpec DS; ParseTypeQualifierListOpt(DS); + D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. ParseDeclaratorInternal(D, DirectDeclParser); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, - DS.TakeAttributes())); + DS.TakeAttributes()), + SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc)); + Loc), + SourceLocation()); } else { // Is a reference DeclSpec DS; @@ -1637,6 +1662,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // [GNU] Retricted references are allowed. // [GNU] Attributes on references are allowed. ParseTypeQualifierListOpt(DS); + D.ExtendWithDeclSpec(DS); if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) @@ -1669,7 +1695,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Remember that we parsed a reference type. It doesn't have type-quals. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, - DS.TakeAttributes())); + DS.TakeAttributes()), + SourceLocation()); } } @@ -1736,37 +1763,42 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } // If this identifier is the name of the current class, it's a // constructor name. - else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope)) + else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)){ D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), CurScope), Tok.getLocation()); // This is a normal identifier. - else + } else D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); 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()) { - D.setOverloadedOperator(Op, OperatorLoc); + 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()) - D.setConversionFunction(ConvType, OperatorLoc); - else + 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)) { - if (TypeTy *Type = ParseClassName()) - D.setDestructor(Type, TildeLoc); - else + // FIXME: Inaccurate. + SourceLocation NameLoc = Tok.getLocation(); + if (TypeTy *Type = ParseClassName()) { + D.setDestructor(Type, TildeLoc, NameLoc); + } else { D.SetIdentifier(0, TildeLoc); + } } else { Diag(Tok, diag::err_expected_class_name); D.SetIdentifier(0, TildeLoc); @@ -1906,13 +1938,14 @@ void Parser::ParseParenDeclarator(Declarator &D) { bool hadGroupingParens = D.hasGroupingParens(); D.setGroupingParens(true); if (AttrList) - D.AddAttributes(AttrList); + D.AddAttributes(AttrList, SourceLocation()); ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. - MatchRHSPunctuation(tok::r_paren, StartLoc); + SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc); D.setGroupingParens(hadGroupingParens); + D.SetRangeEnd(Loc); return; } @@ -1969,16 +2002,18 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, delete AttrList; } - ConsumeParen(); // Eat the closing ')'. + SourceLocation Loc = ConsumeParen(); // Eat the closing ')'. // cv-qualifier-seq[opt]. DeclSpec DS; if (getLang().CPlusPlus) { ParseTypeQualifierListOpt(DS, false /*no attributes*/); + if (!DS.getSourceRange().getEnd().isInvalid()) + Loc = DS.getSourceRange().getEnd(); // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) - ParseExceptionSpecification(); + ParseExceptionSpecification(Loc); } // Remember that we parsed a function type, and remember the attributes. @@ -1987,7 +2022,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, /*variadic*/ false, /*arglist*/ 0, 0, DS.getTypeQualifiers(), - LParenLoc, D)); + LParenLoc, D), + Loc); return; } @@ -2051,8 +2087,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ParseDeclarator(ParmDecl); // Parse GNU attributes, if present. - if (Tok.is(tok::kw___attribute)) - ParmDecl.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + ParmDecl.AddAttributes(AttrList, Loc); + } // Remember this parsed parameter in ParamInfo. IdentifierInfo *ParmII = ParmDecl.getIdentifier(); @@ -2130,23 +2169,26 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, PrototypeScope.Exit(); // If we have the closing ')', eat it. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, LParenLoc); DeclSpec DS; if (getLang().CPlusPlus) { // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, false /*no attributes*/); + if (!DS.getSourceRange().getEnd().isInvalid()) + Loc = DS.getSourceRange().getEnd(); // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) - ParseExceptionSpecification(); + ParseExceptionSpecification(Loc); } // Remember that we parsed a function type, and remember the attributes. D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, &ParamInfo[0], ParamInfo.size(), DS.getTypeQualifiers(), - LParenLoc, D)); + LParenLoc, D), + Loc); } /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator @@ -2207,16 +2249,17 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // Eat the identifier. ConsumeToken(); } - + + // If we have the closing ')', eat it and we're done. + SourceLocation RLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + // Remember that we parsed a function type, and remember the attributes. This // function type is always a K&R style function type, which is not varargs and // has no prototype. D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false, &ParamInfo[0], ParamInfo.size(), - /*TypeQuals*/0, LParenLoc, D)); - - // If we have the closing ')', eat it and we're done. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + /*TypeQuals*/0, LParenLoc, D), + RLoc); } /// [C90] direct-declarator '[' constant-expression[opt] ']' @@ -2230,10 +2273,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // C array syntax has many features, but by-far the most common is [] and [4]. // This code does a fast path to handle some of the most obvious cases. if (Tok.getKind() == tok::r_square) { - MatchRHSPunctuation(tok::r_square, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); // Remember that we parsed the empty array type. OwningExprResult NumElements(Actions); - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc)); + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc), + EndLoc); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -2241,7 +2285,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { OwningExprResult ExprRes(Actions.ActOnNumericConstant(Tok)); ConsumeToken(); - MatchRHSPunctuation(tok::r_square, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); // If there was an error parsing the assignment-expression, recover. if (ExprRes.isInvalid()) @@ -2249,7 +2293,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, - ExprRes.release(), StartLoc)); + ExprRes.release(), StartLoc), + EndLoc); return; } @@ -2300,13 +2345,14 @@ void Parser::ParseBracketDeclarator(Declarator &D) { SkipUntil(tok::r_square); return; } - - MatchRHSPunctuation(tok::r_square, StartLoc); - + + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); + // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, - NumElements.release(), StartLoc)); + NumElements.release(), StartLoc), + EndLoc); } /// [GNU] typeof-specifier: diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 59c086f813..fe08fc5051 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -630,8 +630,11 @@ Parser::DeclTy *Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { } // If attributes exist after the declarator, parse them. - if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.AddAttributes(AttrList, Loc); + } // NOTE: If Sema is the Action module and declarator is an instance field, // this call will *not* return the created decl; LastDeclInGroup will be @@ -691,8 +694,11 @@ Parser::DeclTy *Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { Init = 0; // Attributes are only allowed on the second declarator. - if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.AddAttributes(AttrList, Loc); + } if (Tok.isNot(tok::colon)) ParseDeclarator(DeclaratorInfo); @@ -921,7 +927,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) { /// type-id /// type-id-list ',' type-id /// -bool Parser::ParseExceptionSpecification() { +bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc) { assert(Tok.is(tok::kw_throw) && "expected throw"); SourceLocation ThrowLoc = ConsumeToken(); @@ -937,7 +943,7 @@ bool Parser::ParseExceptionSpecification() { SourceLocation EllipsisLoc = ConsumeToken(); if (!getLang().Microsoft) Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); return false; } @@ -950,6 +956,6 @@ bool Parser::ParseExceptionSpecification() { break; } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); return false; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 7c0b43923d..332ad7789e 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1251,8 +1251,9 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() { // argument decls, decls within the compound expression, etc. This also // allows determining whether a variable reference inside the block is // within or outside of the block. - ParseScope BlockScope(this, Scope::BlockScope|Scope::FnScope|Scope::BreakScope| - Scope::ContinueScope|Scope::DeclScope); + ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope | + Scope::BreakScope | Scope::ContinueScope | + Scope::DeclScope); // Inform sema that we are starting a block. Actions.ActOnBlockStart(CaretLoc, CurScope); @@ -1260,13 +1261,20 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() { // Parse the return type if present. DeclSpec DS; Declarator ParamInfo(DS, Declarator::BlockLiteralContext); + // FIXME: Since the return type isn't actually parsed, it can't be used to + // fill ParamInfo with an initial valid range, so do it manually. + ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation())); // If this block has arguments, parse them. There is no ambiguity here with // the expression case, because the expression case requires a parameter list. if (Tok.is(tok::l_paren)) { ParseParenDeclarator(ParamInfo); // Parse the pieces after the identifier as if we had "int(...)". + // SetIdentifier sets the source range end, but in this case we're past + // that location. + SourceLocation Tmp = ParamInfo.getSourceRange().getEnd(); ParamInfo.SetIdentifier(0, CaretLoc); + ParamInfo.SetRangeEnd(Tmp); if (ParamInfo.getInvalidType()) { // If there was an error parsing the arguments, they may have // tried to use ^(x+y) which requires an argument list. Just @@ -1281,7 +1289,8 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() { // Otherwise, pretend we saw (void). ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, 0, 0, 0, CaretLoc, - ParamInfo)); + ParamInfo), + CaretLoc); // Inform sema that we are starting a block. Actions.ActOnBlockArguments(ParamInfo, CurScope); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 3442d5977a..e8ef8ea61e 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -390,17 +390,22 @@ Parser::OwningExprResult Parser::ParseCXXCondition() { // simple-asm-expr[opt] if (Tok.is(tok::kw_asm)) { - OwningExprResult AsmLabel(ParseSimpleAsm()); + SourceLocation Loc; + OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi); return ExprError(); } DeclaratorInfo.setAsmLabel(AsmLabel.release()); + DeclaratorInfo.SetRangeEnd(Loc); } // If attributes are present, parse them. - if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.AddAttributes(ParseAttributes()); + if (Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.AddAttributes(AttrList, Loc); + } // '=' assignment-expression if (Tok.isNot(tok::equal)) @@ -552,33 +557,41 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { /// ^= &= |= << >> >>= <<= == != /// <= >= && || ++ -- , ->* -> /// () [] -OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { +OverloadedOperatorKind +Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) { assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); + SourceLocation Loc; OverloadedOperatorKind Op = OO_None; switch (NextToken().getKind()) { case tok::kw_new: ConsumeToken(); // 'operator' - ConsumeToken(); // 'new' + Loc = ConsumeToken(); // 'new' if (Tok.is(tok::l_square)) { ConsumeBracket(); // '[' + Loc = Tok.getLocation(); ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' Op = OO_Array_New; } else { Op = OO_New; } + if (EndLoc) + *EndLoc = Loc; return Op; case tok::kw_delete: ConsumeToken(); // 'operator' - ConsumeToken(); // 'delete' + Loc = ConsumeToken(); // 'delete' if (Tok.is(tok::l_square)) { ConsumeBracket(); // '[' + Loc = Tok.getLocation(); ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' Op = OO_Array_Delete; } else { Op = OO_Delete; } + if (EndLoc) + *EndLoc = Loc; return Op; #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ @@ -589,13 +602,19 @@ OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { case tok::l_paren: ConsumeToken(); // 'operator' ConsumeParen(); // '(' + Loc = Tok.getLocation(); ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' + if (EndLoc) + *EndLoc = Loc; return OO_Call; case tok::l_square: ConsumeToken(); // 'operator' ConsumeBracket(); // '[' + Loc = Tok.getLocation(); ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' + if (EndLoc) + *EndLoc = Loc; return OO_Subscript; default: @@ -603,7 +622,9 @@ OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { } ConsumeToken(); // 'operator' - ConsumeAnyToken(); // the operator itself + Loc = ConsumeAnyToken(); // the operator itself + if (EndLoc) + *EndLoc = Loc; return Op; } @@ -620,7 +641,7 @@ OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { /// /// conversion-declarator: /// ptr-operator conversion-declarator[opt] -Parser::TypeTy *Parser::ParseConversionFunctionId() { +Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) { assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); ConsumeToken(); // 'operator' @@ -633,6 +654,8 @@ Parser::TypeTy *Parser::ParseConversionFunctionId() { // ptr-operators. Declarator D(DS, Declarator::TypeNameContext); ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); + if (EndLoc) + *EndLoc = D.getSourceRange().getEnd(); // Finish up the type. Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); @@ -706,15 +729,18 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (Tok.is(tok::l_paren)) { SourceLocation LParen = ConsumeParen(); ParseSpecifierQualifierList(DS); + DeclaratorInfo.SetSourceRange(DS.getSourceRange()); ParseDeclarator(DeclaratorInfo); MatchRHSPunctuation(tok::r_paren, LParen); ParenTypeId = true; } else { if (ParseCXXTypeSpecifierSeq(DS)) DeclaratorInfo.setInvalidType(true); - else + else { + DeclaratorInfo.SetSourceRange(DS.getSourceRange()); ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator); + } ParenTypeId = false; } } @@ -723,9 +749,11 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { // direct-declarator is replaced by a direct-new-declarator. if (ParseCXXTypeSpecifierSeq(DS)) DeclaratorInfo.setInvalidType(true); - else + else { + DeclaratorInfo.SetSourceRange(DS.getSourceRange()); ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator); + } ParenTypeId = false; } if (DeclaratorInfo.getInvalidType()) { @@ -780,10 +808,12 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { } first = false; + SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.release(), LLoc)); + Size.release(), LLoc), + RLoc); - if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid()) + if (RLoc.isInvalid()) return; } } @@ -803,6 +833,7 @@ bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, // The '(' was already consumed. if (isTypeIdInParens()) { ParseSpecifierQualifierList(D.getMutableDeclSpec()); + D.SetSourceRange(D.getDeclSpec().getSourceRange()); ParseDeclarator(D); return D.getInvalidType(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index eb84a4a382..f28767a0fd 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -522,6 +522,7 @@ Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) { D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(), PrevSpec); + D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin()); } // If this declaration was formed with a K&R-style identifier list for the @@ -702,7 +703,7 @@ Parser::OwningExprResult Parser::ParseAsmStringLiteral() { /// [GNU] simple-asm-expr: /// 'asm' '(' asm-string-literal ')' /// -Parser::OwningExprResult Parser::ParseSimpleAsm() { +Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { assert(Tok.is(tok::kw_asm) && "Not an asm!"); SourceLocation Loc = ConsumeToken(); @@ -711,14 +712,20 @@ Parser::OwningExprResult Parser::ParseSimpleAsm() { return ExprError(); } - ConsumeParen(); + Loc = ConsumeParen(); OwningExprResult Result(ParseAsmStringLiteral()); - if (Result.isInvalid()) - SkipUntil(tok::r_paren); - else - MatchRHSPunctuation(tok::r_paren, Loc); + if (Result.isInvalid()) { + SkipUntil(tok::r_paren, true, true); + if (EndLoc) + *EndLoc = Tok.getLocation(); + ConsumeAnyToken(); + } else { + Loc = MatchRHSPunctuation(tok::r_paren, Loc); + if (EndLoc) + *EndLoc = Loc; + } return move(Result); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4bba5e50f1..a3e0232987 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2770,9 +2770,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, Error = Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc, D)); + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc, D), + SourceLocation()); D.SetIdentifier(&II, Loc); - + // Insert this function into translation-unit scope. DeclContext *PrevDC = CurContext; -- 2.40.0