Use ParseUnqualifiedId when parsing id-expressions. This eliminates

yet another copy of the unqualified-id parsing code.

Also, use UnqualifiedId to simplify the Action interface for building
id-expressions. ActOnIdentifierExpr, ActOnCXXOperatorFunctionIdExpr,
ActOnCXXConversionFunctionExpr, and ActOnTemplateIdExpr have all been
removed in favor of the new ActOnIdExpression action.

llvm-svn: 85904
This commit is contained in:
Douglas Gregor 2009-11-03 16:56:39 +00:00
parent e1d5cd9f48
commit a121b75d9d
8 changed files with 145 additions and 200 deletions

View File

@ -854,47 +854,33 @@ public:
virtual SourceRange getExprRange(ExprTy *E) const {
return SourceRange();
}
/// ActOnIdentifierExpr - Parse an identifier in expression context.
/// 'HasTrailingLParen' indicates whether or not the identifier has a '('
/// token immediately after it.
/// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
/// namespace) that the identifier must be a member of.
/// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen,
const CXXScopeSpec *SS = 0,
bool isAddressOfOperand = false){
/// \brief Parsed an id-expression (C++) or identifier (C) in expression
/// context, e.g., the expression "x" that refers to a variable named "x".
///
/// \param S the scope in which this id-expression or identifier occurs.
///
/// \param SS the C++ nested-name-specifier that qualifies the name of the
/// value, e.g., "std::" in "std::sort".
///
/// \param Name the name to which the id-expression refers. In C, this will
/// always be an identifier. In C++, it may also be an overloaded operator,
/// destructor name (if there is a nested-name-specifier), or template-id.
///
/// \param HasTrailingLParen whether the next token following the
/// id-expression or identifier is a left parentheses ('(').
///
/// \param IsAddressOfOperand whether the token that precedes this
/// id-expression or identifier was an ampersand ('&'), indicating that
/// we will be taking the address of this expression.
virtual OwningExprResult ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
bool HasTrailingLParen,
bool IsAddressOfOperand) {
return ExprEmpty();
}
/// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
/// name (e.g., @c operator+ ) as an expression. This is very
/// similar to ActOnIdentifierExpr, except that instead of providing
/// an identifier the parser provides the kind of overloaded
/// operator that was parsed.
virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
Scope *S, SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
bool HasTrailingLParen, const CXXScopeSpec &SS,
bool isAddressOfOperand = false) {
return ExprEmpty();
}
/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
/// name (e.g., @c operator void const *) as an expression. This is
/// very similar to ActOnIdentifierExpr, except that instead of
/// providing an identifier the parser provides the type of the
/// conversion function.
virtual OwningExprResult ActOnCXXConversionFunctionExpr(
Scope *S, SourceLocation OperatorLoc,
TypeTy *Type, bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand = false) {
return ExprEmpty();
}
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
return ExprEmpty();
@ -1711,40 +1697,6 @@ public:
return TypeResult();
}
/// \brief Form a reference to a template-id (that will refer to a function)
/// from a template and a list of template arguments.
///
/// This action forms an expression that references the given template-id,
/// possibly checking well-formedness of the template arguments. It does not
/// imply the declaration of any entity.
///
/// \param SS The scope specifier that may precede the template name.
///
/// \param Template A template whose specialization results in a
/// function or a dependent template.
///
/// \param TemplateNameLoc The location of the template name.
///
/// \param LAngleLoc The location of the left angle bracket ('<') that starts
/// the template argument list.
///
/// \param TemplateArgs The template arguments in the template argument list,
/// which may be empty.
///
/// \param TemplateArgLocs The locations of the template arguments.
///
/// \param RAngleLoc The location of the right angle bracket ('>') that
/// closes the template argument list.
virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc) {
return ExprError();
}
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template

View File

@ -1213,8 +1213,8 @@ private:
bool EnteringContext,
UnqualifiedId &Id);
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool IsExpressionContext,
bool IsDeclarator,
bool AllowDestructorName,
bool AllowConstructorName,
UnqualifiedId &Result);
//===--------------------------------------------------------------------===//

View File

@ -651,7 +651,11 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
Res = Actions.ActOnIdentifierExpr(CurScope, ILoc, II, Tok.is(tok::l_paren));
UnqualifiedId Name;
CXXScopeSpec ScopeSpec;
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name,
Tok.is(tok::l_paren), false);
// These can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(move(Res));
}

View File

@ -309,7 +309,19 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
//
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
/*EnteringContext=*/false,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
Name))
return ExprError();
return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
isAddressOfOperand);
#if 0
// unqualified-id:
// identifier
// operator-function-id
@ -372,6 +384,7 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
} // switch.
assert(0 && "The switch was supposed to take care everything.");
#endif
}
/// ParseCXXCasts - This handles the various ways to cast expressions to another

View File

@ -474,6 +474,7 @@ public:
/// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
DeclarationName GetNameForDeclarator(Declarator &D);
DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
@ -1608,23 +1609,12 @@ public:
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen,
const CXXScopeSpec *SS = 0,
bool isAddressOfOperand = false);
virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(Scope *S,
SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand);
virtual OwningExprResult ActOnCXXConversionFunctionExpr(Scope *S,
SourceLocation OperatorLoc,
TypeTy *Ty,
bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand);
virtual OwningExprResult ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
bool HasTrailingLParen,
bool IsAddressOfOperand);
OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
SourceLocation Loc, bool TypeDependent,
bool ValueDependent,
@ -2545,13 +2535,13 @@ public:
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,

View File

@ -1606,56 +1606,60 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
/// GetNameForDeclarator - Determine the full declaration name for the
/// given Declarator.
DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
UnqualifiedId &Name = D.getName();
return GetNameFromUnqualifiedId(D.getName());
}
/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
return DeclarationName(Name.Identifier);
case UnqualifiedId::IK_OperatorFunctionId:
return Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator);
case UnqualifiedId::IK_ConversionFunctionId: {
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
if (Ty.isNull())
return DeclarationName();
return Context.DeclarationNames.getCXXConversionFunctionName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_Identifier:
return DeclarationName(Name.Identifier);
case UnqualifiedId::IK_ConstructorName: {
QualType Ty = GetTypeFromParser(Name.ConstructorName);
if (Ty.isNull())
return DeclarationName();
return Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_OperatorFunctionId:
return Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator);
case UnqualifiedId::IK_DestructorName: {
QualType Ty = GetTypeFromParser(Name.DestructorName);
if (Ty.isNull())
return DeclarationName();
return Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_ConversionFunctionId: {
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
if (Ty.isNull())
return DeclarationName();
case UnqualifiedId::IK_TemplateId: {
TemplateName TName
return Context.DeclarationNames.getCXXConversionFunctionName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_ConstructorName: {
QualType Ty = GetTypeFromParser(Name.ConstructorName);
if (Ty.isNull())
return DeclarationName();
return Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_DestructorName: {
QualType Ty = GetTypeFromParser(Name.DestructorName);
if (Ty.isNull())
return DeclarationName();
return Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(Ty));
}
case UnqualifiedId::IK_TemplateId: {
TemplateName TName
= TemplateName::getFromVoidPointer(Name.TemplateId->Template);
if (TemplateDecl *Template = TName.getAsTemplateDecl())
return Template->getDeclName();
if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
return Ovl->getDeclName();
return DeclarationName();
if (TemplateDecl *Template = TName.getAsTemplateDecl())
return Template->getDeclName();
if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
return Ovl->getDeclName();
return DeclarationName();
}
}
}
assert(false && "Unknown name kind");
return DeclarationName();
return DeclarationName();
}
/// isNearlyMatchingFunction - Determine whether the C++ functions

View File

@ -436,20 +436,6 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
/// identifier is used in a function call context.
/// SS is only used for a C++ qualified-id (foo::bar) to indicate the
/// class or namespace that the identifier must be a member of.
Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen,
const CXXScopeSpec *SS,
bool isAddressOfOperand) {
return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS,
isAddressOfOperand);
}
/// BuildDeclRefExpr - Build a DeclRefExpr.
Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
@ -654,15 +640,43 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return Owned(Result);
}
Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
bool HasTrailingLParen,
bool IsAddressOfOperand) {
if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
ASTTemplateArgsPtr TemplateArgsPtr(*this,
Name.TemplateId->getTemplateArgs(),
Name.TemplateId->getTemplateArgIsType(),
Name.TemplateId->NumArgs);
return ActOnTemplateIdExpr(SS,
TemplateTy::make(Name.TemplateId->Template),
Name.TemplateId->TemplateNameLoc,
Name.TemplateId->LAngleLoc,
TemplateArgsPtr,
Name.TemplateId->getTemplateArgLocations(),
Name.TemplateId->RAngleLoc);
}
// FIXME: We lose a bunch of source information by doing this. Later,
// we'll want to merge ActOnDeclarationNameExpr's logic into
// ActOnIdExpression.
return ActOnDeclarationNameExpr(S,
Name.StartLocation,
GetNameFromUnqualifiedId(Name),
HasTrailingLParen,
&SS,
IsAddressOfOperand);
}
/// ActOnDeclarationNameExpr - The parser has read some kind of name
/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
/// performs lookup on that name and returns an expression that refers
/// to that name. This routine isn't directly called from the parser,
/// because the parser doesn't know about DeclarationName. Rather,
/// this routine is called by ActOnIdentifierExpr,
/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr,
/// which form the DeclarationName from the corresponding syntactic
/// forms.
/// this routine is called by ActOnIdExpression, which contains a
/// parsed UnqualifiedId.
///
/// HasTrailingLParen indicates whether this identifier is used in a
/// function call context. LookupCtx is only used for a C++
@ -743,8 +757,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
OwningExprResult SelfExpr = ActOnIdentifierExpr(S, SourceLocation(),
II, false);
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
CXXScopeSpec SelfScopeSpec;
OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
SelfName, false, false);
MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
@ -3985,7 +4002,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
// DeclExpr's (created by ActOnIdExpression), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.

View File

@ -22,41 +22,6 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
/// name (e.g., operator void const *) as an expression. This is
/// very similar to ActOnIdentifierExpr, except that instead of
/// providing an identifier the parser provides the type of the
/// conversion function.
Sema::OwningExprResult
Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc,
TypeTy *Ty, bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand) {
//FIXME: Preserve type source info.
QualType ConvType = GetTypeFromParser(Ty);
CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
DeclarationName ConvName
= Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen,
&SS, isAddressOfOperand);
}
/// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator
/// name (e.g., @c operator+ ) as an expression. This is very
/// similar to ActOnIdentifierExpr, except that instead of providing
/// an identifier the parser provides the kind of overloaded
/// operator that was parsed.
Sema::OwningExprResult
Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand) {
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS,
isAddressOfOperand);
}
/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
Action::OwningExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,