]> granicus.if.org Git - clang/commitdiff
Implement Declarator::getSourceRange().
authorSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 9 Feb 2009 18:23:29 +0000 (18:23 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 9 Feb 2009 18:23:29 +0000 (18:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64151 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/DeclSpec.h
include/clang/Parse/Parser.h
lib/Parse/AttributeList.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaDecl.cpp

index 83c0d6179fce0e0db08719af9f343f3f29be6c42..008c161ac885a7fa9cd6c44c8f59c5608e4fd17c 100644 (file)
@@ -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<DeclaratorChunk, 8> 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; }
index eec08cc0a2e8e84d08e715d4696426dde4551755..da29208ccb94eaa29c04bfa942e6db59617d9afd 100644 (file)
 
 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]
index 477d6e363d18f8f45208681deb82ca72a237c96b..eb0527dcf9cb2f21f4e99ecfee4f1f474859e614 100644 (file)
@@ -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) {
index d646ad4cc016e19f5d70d76ce9016c31d3cfbc21..73a09ee39c943b7c88c5bd2a35ec58913ced52ec 100644 (file)
@@ -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:
index 59c086f8131dc9c8879ab802e472458cc6e9a558..fe08fc5051e9b05c42d60c55c4f18029fff622ca 100644 (file)
@@ -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;
 }
index 7c0b43923d60029e2568a1a1905accbfc54d366f..332ad7789ee7b4d8478c6a39051e35fb7fd58206 100644 (file)
@@ -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);
   }
index 3442d5977abd31cde94dddda920019ac29f6b89b..e8ef8ea61ee7c07de713f1568ebeaa5498b16393 100644 (file)
@@ -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();
   }
index eb84a4a3825c1e440a80272ba71727d1458b51da..f28767a0fdb0864350d8a6851de8724bb8de3a94 100644 (file)
@@ -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);
 }
index 4bba5e50f188c55f6153ed2b1122d931ab782f05..a3e0232987c194178bc20fee28cb1ae8aab4af3a 100644 (file)
@@ -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;