From 02a24ee67c0a91bdb0db8a651d5748595652e670 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 3 Nov 2009 16:56:39 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85904 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Action.h | 98 +++++++++--------------------------- include/clang/Parse/Parser.h | 4 +- lib/Parse/ParseExpr.cpp | 6 ++- lib/Parse/ParseExprCXX.cpp | 15 +++++- lib/Sema/Sema.h | 38 ++++++-------- lib/Sema/SemaDecl.cpp | 90 +++++++++++++++++---------------- lib/Sema/SemaExpr.cpp | 59 ++++++++++++++-------- lib/Sema/SemaExprCXX.cpp | 35 ------------- 8 files changed, 145 insertions(+), 200 deletions(-) diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 21e6e2c84c..2ca9e8e30d 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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 diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index fa617ceb7b..a0c06f375e 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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); //===--------------------------------------------------------------------===// diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 477e6fb005..12025c66eb 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -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)); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index dc7974135d..b1250350f7 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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 diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3281fc450c..18dcd851ce 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8d00c09f30..82d467f966 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bdfe91e01e..63d39a05e4 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fad1f3e263..10fff0e241 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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,