Sebastian Redl wrote:
> Hi,
>
> This patch implements Declarator::getSourceRange(). No regressions here,
> but since this is such an important part of parsing, and also because I
> don't really know how to write tests for this, I'd like people to have a
> look at it before I commit.
> The validation of new expressions uses the call a bit (some changes for
> this are also in the patch), but that's all the testing that's really done.
>
Uhh ... actual patch.
Sebastian
Index: test/SemaCXX/new-delete.cpp
===================================================================
--- test/SemaCXX/new-delete.cpp (revision 64079)
+++ test/SemaCXX/new-delete.cpp (working copy)
@@ -64,6 +64,9 @@
(void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
// This must fail, because the member version shouldn't be found.
(void)::new ((S*)0) U; // expected-error {{no matching function for call to
'operator new'}}
+ (void)new (int[]); // expected-error {{array size must be specified in new
expressions}}
+ (void)new int&; // expected-error {{cannot allocate reference type 'int &'
with new}}
+ (void)new (void ()); // expected-error {{cannot allocate function type 'void
(void)' with new}}
// Some lacking cases due to lack of sema support.
}
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h (revision 64079)
+++ include/clang/Parse/Parser.h (working copy)
@@ -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,7 @@
TemplateParameterLists *TemplateParams = 0);
DeclTy *ParseFunctionDefinition(Declarator &D);
void ParseKNRParamDeclarations(Declarator &D);
- OwningExprResult ParseSimpleAsm();
+ OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
OwningExprResult ParseAsmStringLiteral();
// Objective-C External Declarations
@@ -634,7 +630,7 @@
//===--------------------------------------------------------------------===//
// C++ 15: C++ Throw Expression
OwningExprResult ParseThrowExpression();
- bool ParseExceptionSpecification();
+ bool ParseExceptionSpecification(SourceLocation &EndLoc);
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
@@ -899,7 +895,7 @@
TypeTy *ParseTypeName();
void ParseBlockId();
- AttributeList *ParseAttributes();
+ AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
void FuzzyParseMicrosoftDeclSpec();
void ParseTypeofSpecifier(DeclSpec &DS);
@@ -967,8 +963,8 @@
//===--------------------------------------------------------------------===//
// C++ 13.5: Overloaded operators [over.oper]
- OverloadedOperatorKind TryParseOperatorFunctionId();
- TypeTy *ParseConversionFunctionId();
+ OverloadedOperatorKind TryParseOperatorFunctionId(SourceLocation *EndLoc =
0);
+ TypeTy *ParseConversionFunctionId(SourceLocation *EndLoc = 0);
//===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
Index: include/clang/Parse/DeclSpec.h
===================================================================
--- include/clang/Parse/DeclSpec.h (revision 64079)
+++ include/clang/Parse/DeclSpec.h (working copy)
@@ -717,7 +717,8 @@
CXXScopeSpec SS;
IdentifierInfo *Identifier;
SourceLocation IdentifierLoc;
-
+ SourceRange Range;
+
/// Context - Where we are parsing this declarator.
///
TheContext Context;
@@ -731,7 +732,7 @@
/// 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 @@
/// 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,18 @@
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; }
+ void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); }
+
/// 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,6 +863,7 @@
Kind = DK_Normal;
else
Kind = DK_Abstract;
+ SetRangeEnd(Loc);
}
/// setConstructor - Set this declarator to be a C++ constructor
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp (revision 64079)
+++ lib/Sema/SemaExprCXX.cpp (working copy)
@@ -197,10 +197,6 @@
ExprTy **ConstructorArgs, unsigned NumConsArgs,
SourceLocation ConstructorRParen)
{
- // FIXME: Throughout this function, we have rather bad location information.
- // Implementing Declarator::getSourceRange() would go a long way toward
- // fixing that.
-
Expr *ArraySize = 0;
unsigned Skip = 0;
// If the specified type is an array, unwrap it and save the expression.
@@ -208,9 +204,11 @@
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
DeclaratorChunk &Chunk = D.getTypeObject(0);
if (Chunk.Arr.hasStatic)
- return Diag(Chunk.Loc, diag::err_static_illegal_in_new);
+ return Diag(Chunk.Loc, diag::err_static_illegal_in_new)
+ << D.getSourceRange();
if (!Chunk.Arr.NumElts)
- return Diag(Chunk.Loc, diag::err_array_new_needs_size);
+ return Diag(Chunk.Loc, diag::err_array_new_needs_size)
+ << D.getSourceRange();
ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
Skip = 1;
}
@@ -251,9 +249,10 @@
FunctionDecl *OperatorNew = 0;
FunctionDecl *OperatorDelete = 0;
Expr **PlaceArgs = (Expr**)PlacementArgs;
- if (FindAllocationFunctions(StartLoc, UseGlobal, AllocType, ArraySize,
- PlaceArgs, NumPlaceArgs, OperatorNew,
- OperatorDelete))
+ if (FindAllocationFunctions(StartLoc,
+ SourceRange(PlacementLParen, PlacementRParen),
+ UseGlobal, AllocType, ArraySize, PlaceArgs,
+ NumPlaceArgs, OperatorNew, OperatorDelete))
return true;
bool Init = ConstructorLParen.isValid();
@@ -276,13 +275,14 @@
// 2) Otherwise, the object is direct-initialized.
CXXConstructorDecl *Constructor = 0;
Expr **ConsArgs = (Expr**)ConstructorArgs;
+ // FIXME: Should check for primitive/aggregate here, not record.
if (const RecordType *RT = AllocType->getAsRecordType()) {
// FIXME: This is incorrect for when there is an empty initializer and
// no user-defined constructor. Must zero-initialize, not
default-construct.
Constructor = PerformInitializationByConstructor(
AllocType, ConsArgs, NumConsArgs,
- D.getDeclSpec().getSourceRange().getBegin(),
- SourceRange(D.getDeclSpec().getSourceRange().getBegin(),
+ D.getSourceRange().getBegin(),
+ SourceRange(D.getSourceRange().getBegin(),
ConstructorRParen),
RT->getDecl()->getDeclName(),
NumConsArgs != 0 ? IK_Direct : IK_Default);
@@ -336,15 +336,11 @@
} else if(AllocType->isIncompleteType()) {
type = 1;
} else {
- assert(AllocType->isReferenceType() && "What else could it be?");
+ assert(AllocType->isReferenceType() && "Unhandled non-object type.");
type = 2;
}
- SourceRange TyR = D.getDeclSpec().getSourceRange();
- // FIXME: This is very much a guess and won't work for, e.g., pointers.
- if (D.getNumTypeObjects() > 0)
- TyR.setEnd(D.getTypeObject(0).Loc);
- Diag(TyR.getBegin(), diag::err_bad_new_type)
- << AllocType.getAsString() << type << TyR;
+ Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
+ << AllocType << type << D.getSourceRange();
return true;
}
@@ -365,9 +361,10 @@
/// FindAllocationFunctions - Finds the overloads of operator new and delete
/// that are appropriate for the allocation.
-bool Sema::FindAllocationFunctions(SourceLocation StartLoc, bool UseGlobal,
- QualType AllocType, bool IsArray,
- Expr **PlaceArgs, unsigned NumPlaceArgs,
+bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType,
+ bool IsArray, Expr **PlaceArgs,
+ unsigned NumPlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete)
{
@@ -397,7 +394,7 @@
CXXRecordDecl *Record = cast<CXXRecordType>(AllocType->getAsRecordType())
->getDecl();
// FIXME: We fail to find inherited overloads.
- if (FindAllocationOverload(StartLoc, NewName, &AllocArgs[0],
+ if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
AllocArgs.size(), Record, /*AllowMissing=*/true,
OperatorNew))
return true;
@@ -406,7 +403,7 @@
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
- if (FindAllocationOverload(StartLoc, NewName, &AllocArgs[0],
+ if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
OperatorNew))
return true;
@@ -420,19 +417,18 @@
/// FindAllocationOverload - Find an fitting overload for the allocation
/// function in the specified scope.
-bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName
Name,
- Expr** Args, unsigned NumArgs,
- DeclContext *Ctx, bool AllowMissing,
- FunctionDecl *&Operator)
+bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, Expr** Args,
+ unsigned NumArgs, DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator)
{
DeclContext::lookup_iterator Alloc, AllocEnd;
llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Name);
if (Alloc == AllocEnd) {
if (AllowMissing)
return false;
- // FIXME: Bad location information.
return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
- << Name << 0;
+ << Name << 0 << Range;
}
OverloadCandidateSet Candidates;
@@ -467,16 +463,14 @@
case OR_No_Viable_Function:
if (AllowMissing)
return false;
- // FIXME: Bad location information.
Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
- << Name << (unsigned)Candidates.size();
+ << Name << (unsigned)Candidates.size() << Range;
PrintOverloadCandidates(Candidates, /*OnlyViable=*/false);
return true;
case OR_Ambiguous:
- // FIXME: Bad location information.
Diag(StartLoc, diag::err_ovl_ambiguous_call)
- << Name;
+ << Name << Range;
PrintOverloadCandidates(Candidates, /*OnlyViable=*/true);
return true;
}
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h (revision 64079)
+++ lib/Sema/Sema.h (working copy)
@@ -1305,13 +1305,14 @@
ExprTy **ConstructorArgs, unsigned
NumConsArgs,
SourceLocation ConstructorRParen);
bool CheckAllocatedType(QualType AllocType, const Declarator &D);
- bool FindAllocationFunctions(SourceLocation StartLoc, bool UseGlobal,
- QualType AllocType, bool IsArray,
+ bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType, bool
IsArray,
Expr **PlaceArgs, unsigned NumPlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete);
- bool FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
- Expr** Args, unsigned NumArgs, DeclContext *Ctx,
+ bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, Expr** Args,
+ unsigned NumArgs, DeclContext *Ctx,
bool AllowMissing, FunctionDecl *&Operator);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp (revision 64079)
+++ lib/AST/Type.cpp (working copy)
@@ -96,7 +96,7 @@
}
bool Type::isObjectType() const {
- if (isa<FunctionType>(CanonicalType))
+ if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType))
return false;
if (const ASQualType *AS = dyn_cast<ASQualType>(CanonicalType))
return AS->getBaseType()->isObjectType();
Index: lib/Parse/AttributeList.cpp
===================================================================
--- lib/Parse/AttributeList.cpp (revision 64079)
+++ lib/Parse/AttributeList.cpp (working copy)
@@ -16,7 +16,7 @@
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: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp (revision 64079)
+++ lib/Parse/ParseDecl.cpp (working copy)
@@ -76,7 +76,7 @@
/// 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 @@
}
}
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 @@
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;
+ D.AddAttributes(ParseAttributes(&Loc));
+ D.SetRangeEnd(Loc);
+ }
// Inform the current actions module that we just parsed this declarator.
LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup);
@@ -356,8 +365,11 @@
// 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;
+ D.AddAttributes(ParseAttributes(&Loc));
+ D.SetRangeEnd(Loc);
+ }
ParseDeclarator(D);
}
@@ -1020,11 +1032,14 @@
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;
+ DeclaratorInfo.D.AddAttributes(ParseAttributes(&Loc));
+ DeclaratorInfo.D.SetRangeEnd(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))
@@ -1037,8 +1052,11 @@
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;
+ Fields.back().D.AddAttributes(ParseAttributes(&Loc));
+ Fields.back().D.SetRangeEnd(Loc);
+ }
}
}
@@ -1586,6 +1604,10 @@
SourceLocation Loc = ConsumeToken();
DeclSpec DS;
ParseTypeQualifierListOpt(DS);
+ if (DS.getSourceRange().getEnd().isInvalid())
+ D.SetRangeEnd(Loc);
+ else
+ D.SetRangeEnd(DS.getSourceRange().getEnd());
// Recurse to parse whatever is left.
ParseDeclaratorInternal(D, DirectDeclParser);
@@ -1608,13 +1630,17 @@
}
// Otherwise, '*' -> pointer, '^' -> block, '&' -> reference.
- SourceLocation Loc = ConsumeToken(); // Eat the * or &.
+ SourceLocation Loc = ConsumeToken(); // Eat the *, ^ or &.
if (Kind == tok::star || (Kind == tok::caret && getLang().Blocks)) {
// Is a pointer.
DeclSpec DS;
ParseTypeQualifierListOpt(DS);
+ if (DS.getSourceRange().getEnd().isInvalid())
+ D.SetRangeEnd(Loc);
+ else
+ D.SetRangeEnd(DS.getSourceRange().getEnd());
// Recursively parse the declarator.
ParseDeclaratorInternal(D, DirectDeclParser);
@@ -1637,6 +1663,10 @@
// [GNU] Retricted references are allowed.
// [GNU] Attributes on references are allowed.
ParseTypeQualifierListOpt(DS);
+ if (DS.getSourceRange().getEnd().isInvalid())
+ D.SetRangeEnd(Loc);
+ else
+ D.SetRangeEnd(DS.getSourceRange().getEnd());
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
@@ -1736,40 +1766,51 @@
}
// 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());
+ D.SetRangeEnd(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()) {
+ if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) {
D.setOverloadedOperator(Op, OperatorLoc);
} else {
// This must be a conversion function (C++ [class.conv.fct]).
- if (TypeTy *ConvType = ParseConversionFunctionId())
+ if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc))
D.setConversionFunction(ConvType, OperatorLoc);
- else
+ else {
D.SetIdentifier(0, Tok.getLocation());
+ EndLoc = Tok.getLocation();
+ }
}
+ D.SetRangeEnd(EndLoc);
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())
+ // FIXME: Inaccurate.
+ SourceLocation NameLoc = Tok.getLocation();
+ if (TypeTy *Type = ParseClassName()) {
D.setDestructor(Type, TildeLoc);
- else
+ D.SetRangeEnd(NameLoc);
+ } else {
D.SetIdentifier(0, TildeLoc);
+ D.SetRangeEnd(NameLoc);
+ }
} else {
Diag(Tok, diag::err_expected_class_name);
D.SetIdentifier(0, TildeLoc);
+ D.SetRangeEnd(TildeLoc);
}
goto PastIdentifier;
}
@@ -1779,6 +1820,7 @@
if (afterCXXScope) {
Diag(Tok, diag::err_expected_unqualified_id);
D.SetIdentifier(0, Tok.getLocation());
+ D.SetRangeEnd(Tok.getLocation());
D.setInvalidType(true);
goto PastIdentifier;
}
@@ -1910,9 +1952,10 @@
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,17 +2012,20 @@
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);
}
+ D.SetRangeEnd(Loc);
// Remember that we parsed a function type, and remember the attributes.
// int() -> no prototype, no '...'.
@@ -2130,17 +2176,20 @@
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);
}
+ D.SetRangeEnd(Loc);
// Remember that we parsed a function type, and remember the attributes.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
@@ -2214,9 +2263,9 @@
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);
+ D.SetRangeEnd(MatchRHSPunctuation(tok::r_paren, LParenLoc));
}
/// [C90] direct-declarator '[' constant-expression[opt] ']'
@@ -2230,10 +2279,11 @@
// 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.SetRangeEnd(EndLoc);
return;
} else if (Tok.getKind() == tok::numeric_constant &&
GetLookAheadToken(1).is(tok::r_square)) {
@@ -2241,7 +2291,7 @@
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())
@@ -2250,6 +2300,7 @@
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0,
ExprRes.release(), StartLoc));
+ D.SetRangeEnd(EndLoc);
return;
}
@@ -2300,13 +2351,14 @@
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));
+ D.SetRangeEnd(EndLoc);
}
/// [GNU] typeof-specifier:
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp (revision 64079)
+++ lib/Parse/ParseExpr.cpp (working copy)
@@ -1251,8 +1251,9 @@
// 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 @@
// Parse the return type if present.
DeclSpec DS;
Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
+ // FIXME: Since the return type isn't actually parsed, need some fake
+ // location info for the declarator.
+ 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
@@ -1282,6 +1290,7 @@
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
0, 0, 0, CaretLoc,
ParamInfo));
+ ParamInfo.SetRangeEnd(CaretLoc);
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(ParamInfo, CurScope);
}
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp (revision 64079)
+++ lib/Parse/ParseDeclCXX.cpp (working copy)
@@ -630,8 +630,11 @@
}
// 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;
+ DeclaratorInfo.AddAttributes(ParseAttributes(&Loc));
+ DeclaratorInfo.SetRangeEnd(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 @@
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;
+ DeclaratorInfo.AddAttributes(ParseAttributes(&Loc));
+ DeclaratorInfo.SetRangeEnd(Loc);
+ }
if (Tok.isNot(tok::colon))
ParseDeclarator(DeclaratorInfo);
@@ -921,7 +927,7 @@
/// 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 @@
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 @@
break;
}
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
return false;
}
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp (revision 64079)
+++ lib/Parse/ParseExprCXX.cpp (working copy)
@@ -390,17 +390,22 @@
// 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;
+ DeclaratorInfo.AddAttributes(ParseAttributes(&Loc));
+ DeclaratorInfo.SetRangeEnd(Loc);
+ }
// '=' assignment-expression
if (Tok.isNot(tok::equal))
@@ -552,33 +557,41 @@
/// ^= &= |= << >> >>= <<= == !=
/// <= >= && || ++ -- , ->* ->
/// () []
-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 @@
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 @@
}
ConsumeToken(); // 'operator'
- ConsumeAnyToken(); // the operator itself
+ Loc = ConsumeAnyToken(); // the operator itself
+ if (EndLoc)
+ *EndLoc = Loc;
return Op;
}
@@ -620,7 +641,7 @@
///
/// 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 @@
// 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 @@
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 @@
// 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()) {
@@ -783,8 +811,10 @@
D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false,
/*star=*/false,
Size.release(), LLoc));
- if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
+ SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
+ if (RLoc.isInvalid())
return;
+ D.SetRangeEnd(RLoc);
}
}
@@ -803,6 +833,7 @@
// The '(' was already consumed.
if (isTypeIdInParens()) {
ParseSpecifierQualifierList(D.getMutableDeclSpec());
+ D.SetSourceRange(D.getDeclSpec().getSourceRange());
ParseDeclarator(D);
return D.getInvalidType();
}
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp (revision 64079)
+++ lib/Parse/Parser.cpp (working copy)
@@ -702,7 +702,7 @@
/// [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 +711,20 @@
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);
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits