Replace the code that parses member access expressions after "." or
"->" with a use of ParseUnqualifiedId. Collapse ActOnMemberReferenceExpr, ActOnDestructorReferenceExpr (both of them), ActOnOverloadedOperatorReferenceExpr, ActOnConversionOperatorReferenceExpr, and ActOnMemberTemplateIdReferenceExpr into a single, new action ActOnMemberAccessExpr that does the same thing more cleanly (and can keep more source-location information). llvm-svn: 85930
This commit is contained in:
parent
d697debebf
commit
30d60cb36e
|
@ -216,7 +216,8 @@ def err_declaration_does_not_declare_param : Error<
|
|||
def err_no_matching_param : Error<"parameter named %0 is missing">;
|
||||
|
||||
/// C++ parser diagnostics
|
||||
def err_expected_unqualified_id : Error<"expected unqualified-id">;
|
||||
def err_expected_unqualified_id : Error<
|
||||
"expected %select{identifier|unqualified-id}0">;
|
||||
def err_func_def_no_params : Error<
|
||||
"function definition does not declare parameters">;
|
||||
def err_expected_lparen_after_type : Error<
|
||||
|
@ -233,6 +234,8 @@ def err_expected_catch : Error<"expected catch">;
|
|||
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
|
||||
def err_using_namespace_in_class : Error<
|
||||
"'using namespace' in class not allowed">;
|
||||
def err_ident_in_pseudo_dtor_not_a_type : Error<
|
||||
"identifier %0 in pseudo-destructor expression does not name a type">;
|
||||
|
||||
// C++ derived classes
|
||||
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
|
||||
|
|
|
@ -1725,8 +1725,6 @@ def err_throw_incomplete_ptr : Error<
|
|||
def err_return_in_constructor_handler : Error<
|
||||
"return in the catch of a function try block of a constructor is illegal">;
|
||||
|
||||
def err_ident_in_pseudo_dtor_not_a_type : Error<
|
||||
"identifier %0 in pseudo-destructor expression does not name a type">;
|
||||
def err_operator_arrow_circular : Error<
|
||||
"circular pointer delegation detected">;
|
||||
def err_pseudo_dtor_base_not_scalar : Error<
|
||||
|
|
|
@ -922,16 +922,42 @@ public:
|
|||
SourceLocation RLoc) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
|
||||
/// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
|
||||
/// of the form \c x.m or \c p->m.
|
||||
///
|
||||
/// \param S the scope in which the member access expression occurs.
|
||||
///
|
||||
/// \param Base the class or pointer to class into which this member
|
||||
/// access expression refers, e.g., \c x in \c x.m.
|
||||
///
|
||||
/// \param OpLoc the location of the "." or "->" operator.
|
||||
///
|
||||
/// \param OpKind the kind of member access operator, which will be either
|
||||
/// tok::arrow ("->") or tok::period (".").
|
||||
///
|
||||
/// \param SS in C++, the nested-name-specifier that precedes the member
|
||||
/// name, if any.
|
||||
///
|
||||
/// \param Member the name of the member that we are referring to. In C,
|
||||
/// this will always store an identifier; in C++, we may also have operator
|
||||
/// names, conversion function names, destructors, and template names.
|
||||
///
|
||||
/// \param ObjCImpDecl the Objective-C implementation declaration.
|
||||
/// FIXME: Do we really need this?
|
||||
///
|
||||
/// \param HasTrailingLParen whether this member name is immediately followed
|
||||
/// by a left parentheses ('(').
|
||||
virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
|
||||
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
|
||||
/// This provides the location of the left/right parens and a list of comma
|
||||
/// locations. There are guaranteed to be one fewer commas than arguments,
|
||||
|
@ -1361,123 +1387,6 @@ public:
|
|||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnDestructorReferenceExpr - Parsed a destructor reference, for example:
|
||||
///
|
||||
/// t->~T();
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// \brief Parsed a C++ destructor reference that refers to a type.
|
||||
///
|
||||
/// This action is used when parsing a destructor reference that uses a
|
||||
/// template-id, e.g.,
|
||||
///
|
||||
/// \code
|
||||
/// t->~Tmpl<T1, T2>
|
||||
/// \endcode
|
||||
///
|
||||
/// \param S the scope in which the destructor reference occurs.
|
||||
/// \param Base the base object of the destructor reference expression.
|
||||
/// \param OpLoc the location of the operator ('.' or '->').
|
||||
/// \param OpKind the kind of the destructor reference operator ('.' or '->').
|
||||
/// \param TypeRange the source range that covers the destructor type.
|
||||
/// \param Type the type that is being destroyed.
|
||||
/// \param SS the scope specifier that precedes the destructor name.
|
||||
/// \param HasTrailingLParen whether the destructor name is followed by a '('.
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceRange TypeRange,
|
||||
TypeTy *Type,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
|
||||
/// reference, for example:
|
||||
///
|
||||
/// t.operator++();
|
||||
virtual OwningExprResult
|
||||
ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
OverloadedOperatorKind OverOpKind,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion
|
||||
/// function reference, for example:
|
||||
///
|
||||
/// t.operator int();
|
||||
virtual OwningExprResult
|
||||
ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
TypeTy *Ty,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// \brief Parsed a reference to a member template-id.
|
||||
///
|
||||
/// This callback will occur instead of ActOnMemberReferenceExpr() when the
|
||||
/// member in question is a template for which the code provides an
|
||||
/// explicitly-specified template argument list, e.g.,
|
||||
///
|
||||
/// \code
|
||||
/// x.f<int>()
|
||||
/// \endcode
|
||||
///
|
||||
/// \param S the scope in which the member reference expression occurs
|
||||
///
|
||||
/// \param Base the expression to the left of the "." or "->".
|
||||
///
|
||||
/// \param OpLoc the location of the "." or "->".
|
||||
///
|
||||
/// \param OpKind the kind of operator, which will be "." or "->".
|
||||
///
|
||||
/// \param SS the scope specifier that precedes the template-id in, e.g.,
|
||||
/// \c x.Base::f<int>().
|
||||
///
|
||||
/// \param Template the declaration of the template that is being referenced.
|
||||
///
|
||||
/// \param TemplateNameLoc the location of the template name referred to by
|
||||
/// \p Template.
|
||||
///
|
||||
/// \param LAngleLoc the location of the left angle bracket ('<')
|
||||
///
|
||||
/// \param TemplateArgs the (possibly-empty) template argument list provided
|
||||
/// as part of the member reference.
|
||||
///
|
||||
/// \param RAngleLoc the location of the right angle bracket ('>')
|
||||
virtual OwningExprResult
|
||||
ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
// FIXME: "template" keyword?
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
|
||||
/// (C++ [intro.execution]p12).
|
||||
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
|
||||
|
|
|
@ -1216,10 +1216,12 @@ private:
|
|||
IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
bool EnteringContext,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Id);
|
||||
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
bool AllowDestructorName,
|
||||
bool AllowConstructorName,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Result);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -2314,6 +2314,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
/*EnteringContext=*/true,
|
||||
/*AllowDestructorName=*/true,
|
||||
/*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(),
|
||||
/*ObjectType=*/0,
|
||||
D.getName())) {
|
||||
D.SetIdentifier(0, Tok.getLocation());
|
||||
D.setInvalidType(true);
|
||||
|
@ -2348,7 +2349,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
Diag(Tok, diag::err_expected_member_name_or_semi)
|
||||
<< D.getDeclSpec().getSourceRange();
|
||||
else if (getLang().CPlusPlus)
|
||||
Diag(Tok, diag::err_expected_unqualified_id);
|
||||
Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
|
||||
else
|
||||
Diag(Tok, diag::err_expected_ident_lparen);
|
||||
D.SetIdentifier(0, Tok.getLocation());
|
||||
|
|
|
@ -968,6 +968,21 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
|||
ConsumeToken();
|
||||
}
|
||||
|
||||
UnqualifiedId Name;
|
||||
if (ParseUnqualifiedId(SS,
|
||||
/*EnteringContext=*/false,
|
||||
/*AllowDestructorName=*/true,
|
||||
/*AllowConstructorName=*/false,
|
||||
ObjectType,
|
||||
Name))
|
||||
return ExprError();
|
||||
|
||||
if (!LHS.isInvalid())
|
||||
LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
|
||||
SS, Name, ObjCImpDecl,
|
||||
Tok.is(tok::l_paren));
|
||||
|
||||
#if 0
|
||||
if (Tok.is(tok::identifier)) {
|
||||
if (!LHS.isInvalid())
|
||||
LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
|
||||
|
@ -1072,6 +1087,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
|||
Diag(Tok, diag::err_expected_ident);
|
||||
return ExprError();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case tok::plusplus: // postfix-expression: postfix-expression '++'
|
||||
|
|
|
@ -315,76 +315,13 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
|
|||
/*EnteringContext=*/false,
|
||||
/*AllowDestructorName=*/false,
|
||||
/*AllowConstructorName=*/false,
|
||||
/*ObjectType=*/0,
|
||||
Name))
|
||||
return ExprError();
|
||||
|
||||
return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
|
||||
isAddressOfOperand);
|
||||
|
||||
#if 0
|
||||
// unqualified-id:
|
||||
// identifier
|
||||
// operator-function-id
|
||||
// conversion-function-id
|
||||
// '~' class-name [TODO]
|
||||
// template-id
|
||||
//
|
||||
switch (Tok.getKind()) {
|
||||
default:
|
||||
return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
|
||||
|
||||
case tok::identifier: {
|
||||
// Consume the identifier so that we can see if it is followed by a '('.
|
||||
IdentifierInfo &II = *Tok.getIdentifierInfo();
|
||||
SourceLocation L = ConsumeToken();
|
||||
return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
|
||||
&SS, isAddressOfOperand);
|
||||
}
|
||||
|
||||
case tok::kw_operator: {
|
||||
SourceLocation OperatorLoc = Tok.getLocation();
|
||||
if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
|
||||
return Actions.ActOnCXXOperatorFunctionIdExpr(
|
||||
CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
|
||||
isAddressOfOperand);
|
||||
if (TypeTy *Type = ParseConversionFunctionId())
|
||||
return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
|
||||
Tok.is(tok::l_paren), SS,
|
||||
isAddressOfOperand);
|
||||
|
||||
// We already complained about a bad conversion-function-id,
|
||||
// above.
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
case tok::annot_template_id: {
|
||||
TemplateIdAnnotation *TemplateId
|
||||
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
||||
assert((TemplateId->Kind == TNK_Function_template ||
|
||||
TemplateId->Kind == TNK_Dependent_template_name) &&
|
||||
"A template type name is not an ID expression");
|
||||
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
|
||||
TemplateId->getTemplateArgs(),
|
||||
TemplateId->getTemplateArgIsType(),
|
||||
TemplateId->NumArgs);
|
||||
|
||||
OwningExprResult Result
|
||||
= Actions.ActOnTemplateIdExpr(SS,
|
||||
TemplateTy::make(TemplateId->Template),
|
||||
TemplateId->TemplateNameLoc,
|
||||
TemplateId->LAngleLoc,
|
||||
TemplateArgsPtr,
|
||||
TemplateId->getTemplateArgLocations(),
|
||||
TemplateId->RAngleLoc);
|
||||
ConsumeToken(); // Consume the template-id token
|
||||
return move(Result);
|
||||
}
|
||||
|
||||
} // switch.
|
||||
|
||||
assert(0 && "The switch was supposed to take care everything.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// ParseCXXCasts - This handles the various ways to cast expressions to another
|
||||
|
@ -806,6 +743,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
bool EnteringContext,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Id) {
|
||||
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
|
||||
|
||||
|
@ -814,14 +752,13 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
switch (Id.getKind()) {
|
||||
case UnqualifiedId::IK_Identifier:
|
||||
TNK = Actions.isTemplateName(CurScope, *Id.Identifier, Id.StartLocation,
|
||||
&SS, /*ObjectType=*/0, EnteringContext,
|
||||
Template);
|
||||
&SS, ObjectType, EnteringContext, Template);
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_OperatorFunctionId: {
|
||||
// FIXME: Temporary hack: warn that we are completely ignoring the
|
||||
// template arguments for now.
|
||||
// Parse the enclosed template argument list.
|
||||
// Parse the enclosed template argument list and throw it away.
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
TemplateArgList TemplateArgs;
|
||||
TemplateArgIsTypeList TemplateArgIsType;
|
||||
|
@ -840,15 +777,32 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
}
|
||||
|
||||
case UnqualifiedId::IK_ConstructorName:
|
||||
TNK = Actions.isTemplateName(CurScope, *Name, NameLoc,
|
||||
&SS, /*ObjectType=*/0, EnteringContext,
|
||||
Template);
|
||||
TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, &SS, ObjectType,
|
||||
EnteringContext, Template);
|
||||
break;
|
||||
|
||||
case UnqualifiedId::IK_DestructorName:
|
||||
TNK = Actions.isTemplateName(CurScope, *Name, NameLoc,
|
||||
&SS, /*ObjectType=*/0, EnteringContext,
|
||||
Template);
|
||||
if (ObjectType) {
|
||||
Template = Actions.ActOnDependentTemplateName(SourceLocation(), *Name,
|
||||
NameLoc, SS, ObjectType);
|
||||
TNK = TNK_Dependent_template_name;
|
||||
if (!Template.get())
|
||||
return true;
|
||||
} else {
|
||||
TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, &SS, ObjectType,
|
||||
EnteringContext, Template);
|
||||
|
||||
if (TNK == TNK_Non_template && Id.DestructorName == 0) {
|
||||
// The identifier following the destructor did not refer to a template
|
||||
// or to a type. Complain.
|
||||
if (ObjectType)
|
||||
Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
|
||||
<< Name;
|
||||
else
|
||||
Diag(NameLoc, diag::err_destructor_class_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -974,6 +928,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
bool AllowDestructorName,
|
||||
bool AllowConstructorName,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Result) {
|
||||
// unqualified-id:
|
||||
// identifier
|
||||
|
@ -997,7 +952,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
|||
// If the next token is a '<', we may have a template.
|
||||
if (Tok.is(tok::less))
|
||||
return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
|
||||
Result);
|
||||
ObjectType, Result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1110,7 +1065,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
|||
// If the next token is a '<', we may have a template.
|
||||
if (Tok.is(tok::less))
|
||||
return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
|
||||
EnteringContext, Result);
|
||||
EnteringContext, ObjectType,
|
||||
Result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1166,24 +1122,30 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
|||
IdentifierInfo *ClassName = Tok.getIdentifierInfo();
|
||||
SourceLocation ClassNameLoc = ConsumeToken();
|
||||
|
||||
if (Tok.is(tok::less)) {
|
||||
Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
|
||||
return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
|
||||
EnteringContext, ObjectType, Result);
|
||||
}
|
||||
|
||||
// Note that this is a destructor name.
|
||||
Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
|
||||
CurScope, &SS);
|
||||
if (!Ty) {
|
||||
Diag(ClassNameLoc, diag::err_destructor_class_name);
|
||||
if (ObjectType)
|
||||
Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
|
||||
<< ClassName;
|
||||
else
|
||||
Diag(ClassNameLoc, diag::err_destructor_class_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
|
||||
|
||||
if (Tok.is(tok::less))
|
||||
return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
|
||||
EnteringContext, Result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Diag(Tok, diag::err_expected_unqualified_id);
|
||||
Diag(Tok, diag::err_expected_unqualified_id)
|
||||
<< getLang().CPlusPlus;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1714,13 +1714,14 @@ public:
|
|||
const CXXScopeSpec *SS,
|
||||
NamedDecl *FirstQualifierInScope = 0);
|
||||
|
||||
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member,
|
||||
DeclPtrTy ImplDecl,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
bool HasTrailingLParen);
|
||||
|
||||
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
|
||||
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
|
||||
FunctionDecl *FDecl,
|
||||
|
@ -2096,52 +2097,6 @@ public:
|
|||
tok::TokenKind OpKind,
|
||||
TypeTy *&ObjectType);
|
||||
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen);
|
||||
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceRange TypeRange,
|
||||
TypeTy *Type,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen);
|
||||
|
||||
virtual OwningExprResult
|
||||
ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
OverloadedOperatorKind OverOpKind,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
virtual OwningExprResult
|
||||
ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
TypeTy *Ty,
|
||||
const CXXScopeSpec *SS = 0);
|
||||
|
||||
virtual OwningExprResult
|
||||
ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
// FIXME: "template" keyword?
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
|
||||
/// non-empty, will create a new CXXExprWithTemporaries expression.
|
||||
/// Otherwise, just returs the passed in expression.
|
||||
|
|
|
@ -2479,13 +2479,72 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
return ExprError();
|
||||
}
|
||||
|
||||
Action::OwningExprResult
|
||||
Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member,
|
||||
DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) {
|
||||
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
|
||||
DeclarationName(&Member), ObjCImpDecl, SS);
|
||||
Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
bool HasTrailingLParen) {
|
||||
if (Member.getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
TemplateName Template
|
||||
= TemplateName::getFromVoidPointer(Member.TemplateId->Template);
|
||||
|
||||
// FIXME: We're going to end up looking up the template based on its name,
|
||||
// twice!
|
||||
DeclarationName Name;
|
||||
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
|
||||
Name = ActualTemplate->getDeclName();
|
||||
else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
|
||||
Name = Ovl->getDeclName();
|
||||
else
|
||||
Name = Template.getAsDependentTemplateName()->getName();
|
||||
|
||||
// Translate the parser's template argument list in our AST format.
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(*this,
|
||||
Member.TemplateId->getTemplateArgs(),
|
||||
Member.TemplateId->getTemplateArgIsType(),
|
||||
Member.TemplateId->NumArgs);
|
||||
|
||||
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
|
||||
translateTemplateArguments(TemplateArgsPtr,
|
||||
Member.TemplateId->getTemplateArgLocations(),
|
||||
TemplateArgs);
|
||||
TemplateArgsPtr.release();
|
||||
|
||||
// Do we have the save the actual template name? We might need it...
|
||||
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
|
||||
Member.TemplateId->TemplateNameLoc,
|
||||
Name, true, Member.TemplateId->LAngleLoc,
|
||||
TemplateArgs.data(), TemplateArgs.size(),
|
||||
Member.TemplateId->RAngleLoc, DeclPtrTy(),
|
||||
&SS);
|
||||
}
|
||||
|
||||
// FIXME: We lose a lot of source information by mapping directly to the
|
||||
// DeclarationName.
|
||||
OwningExprResult Result
|
||||
= BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
|
||||
Member.getSourceRange().getBegin(),
|
||||
GetNameFromUnqualifiedId(Member),
|
||||
ObjCImpDecl, &SS);
|
||||
|
||||
if (Result.isInvalid() || HasTrailingLParen ||
|
||||
Member.getKind() != UnqualifiedId::IK_DestructorName)
|
||||
return move(Result);
|
||||
|
||||
// The only way a reference to a destructor can be used is to
|
||||
// immediately call them. Since the next token is not a '(', produce a
|
||||
// diagnostic and build the call now.
|
||||
Expr *E = (Expr *)Result.get();
|
||||
SourceLocation ExpectedLParenLoc
|
||||
= PP.getLocForEndOfToken(Member.getSourceRange().getEnd());
|
||||
Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
|
||||
<< isa<CXXPseudoDestructorExpr>(E)
|
||||
<< CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
|
||||
|
||||
return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
|
||||
MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
|
||||
|
|
|
@ -2114,110 +2114,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
return move(Base);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
if (SS.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
QualType BaseType;
|
||||
if (isUnknownSpecialization(SS))
|
||||
BaseType = Context.getTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
|
||||
ClassName);
|
||||
else {
|
||||
TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
|
||||
|
||||
// FIXME: If Base is dependent, we might not be able to resolve it here.
|
||||
if (!BaseTy) {
|
||||
Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
|
||||
<< ClassName;
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
BaseType = GetTypeFromParser(BaseTy);
|
||||
}
|
||||
|
||||
return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
|
||||
SourceRange(ClassNameLoc),
|
||||
BaseType.getAsOpaquePtr(),
|
||||
SS, HasTrailingLParen);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceRange TypeRange,
|
||||
TypeTy *T,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
QualType Type = GetTypeFromParser(T);
|
||||
CanQualType CanType = Context.getCanonicalType(Type);
|
||||
DeclarationName DtorName =
|
||||
Context.DeclarationNames.getCXXDestructorName(CanType);
|
||||
|
||||
OwningExprResult Result
|
||||
= BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
|
||||
TypeRange.getBegin(), DtorName, DeclPtrTy(),
|
||||
&SS);
|
||||
if (Result.isInvalid() || HasTrailingLParen)
|
||||
return move(Result);
|
||||
|
||||
// The only way a reference to a destructor can be used is to
|
||||
// immediately call them. Since the next token is not a '(', produce a
|
||||
// diagnostic and build the call now.
|
||||
Expr *E = (Expr *)Result.get();
|
||||
SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
|
||||
Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
|
||||
<< isa<CXXPseudoDestructorExpr>(E)
|
||||
<< CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
|
||||
|
||||
return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
|
||||
MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
Sema::ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
OverloadedOperatorKind OverOpKind,
|
||||
const CXXScopeSpec *SS) {
|
||||
if (SS && SS->isInvalid())
|
||||
return ExprError();
|
||||
|
||||
DeclarationName Name =
|
||||
Context.DeclarationNames.getCXXOperatorName(OverOpKind);
|
||||
|
||||
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
|
||||
Name, DeclPtrTy(), SS);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
TypeTy *Ty,
|
||||
const CXXScopeSpec *SS) {
|
||||
if (SS && SS->isInvalid())
|
||||
return ExprError();
|
||||
|
||||
//FIXME: Preserve type source info.
|
||||
QualType ConvType = GetTypeFromParser(Ty);
|
||||
CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
|
||||
DeclarationName ConvName =
|
||||
Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
|
||||
|
||||
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
|
||||
ConvName, DeclPtrTy(), SS);
|
||||
}
|
||||
|
||||
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
|
||||
CXXMethodDecl *Method) {
|
||||
MemberExpr *ME =
|
||||
|
|
|
@ -1336,41 +1336,6 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
|
|||
RAngleLoc);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
TemplateTy TemplateD,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgsIn,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
TemplateName Template = TemplateD.getAsVal<TemplateName>();
|
||||
|
||||
// FIXME: We're going to end up looking up the template based on its name,
|
||||
// twice!
|
||||
DeclarationName Name;
|
||||
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
|
||||
Name = ActualTemplate->getDeclName();
|
||||
else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
|
||||
Name = Ovl->getDeclName();
|
||||
else
|
||||
Name = Template.getAsDependentTemplateName()->getName();
|
||||
|
||||
// Translate the parser's template argument list in our AST format.
|
||||
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
|
||||
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
|
||||
TemplateArgsIn.release();
|
||||
|
||||
// Do we have the save the actual template name? We might need it...
|
||||
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc,
|
||||
Name, true, LAngleLoc,
|
||||
TemplateArgs.data(), TemplateArgs.size(),
|
||||
RAngleLoc, DeclPtrTy(), &SS);
|
||||
}
|
||||
|
||||
/// \brief Form a dependent template name.
|
||||
///
|
||||
/// This action forms a dependent template name given the template
|
||||
|
|
|
@ -1034,9 +1034,9 @@ public:
|
|||
SourceLocation OpLoc,
|
||||
SourceLocation AccessorLoc,
|
||||
IdentifierInfo &Accessor) {
|
||||
return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
|
||||
return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
|
||||
tok::period, AccessorLoc,
|
||||
Accessor,
|
||||
DeclarationName(&Accessor),
|
||||
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
|
||||
}
|
||||
|
||||
|
@ -1568,7 +1568,7 @@ public:
|
|||
SS.setScopeRep(Qualifier);
|
||||
|
||||
// FIXME: We're going to end up looking up the template based on its name,
|
||||
// twice! Also, duplicates part of Sema::ActOnMemberTemplateIdReferenceExpr.
|
||||
// twice! Also, duplicates part of Sema::BuildMemberAccessExpr.
|
||||
DeclarationName Name;
|
||||
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
|
||||
Name = ActualTemplate->getDeclName();
|
||||
|
|
|
@ -5,8 +5,8 @@ class X {};
|
|||
void test() {
|
||||
X x;
|
||||
|
||||
x.int; // expected-error{{expected identifier}}
|
||||
x.~int(); // expected-error{{expected identifier}}
|
||||
x.int; // expected-error{{expected unqualified-id}}
|
||||
x.~int(); // expected-error{{expected the class name}}
|
||||
x.operator; // expected-error{{missing type specifier after 'operator'}}
|
||||
x.operator typedef; // expected-error{{missing type specifier after 'operator'}}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ void test() {
|
|||
void test2() {
|
||||
X *x;
|
||||
|
||||
x->int; // expected-error{{expected identifier}}
|
||||
x->~int(); // expected-error{{expected identifier}}
|
||||
x->int; // expected-error{{expected unqualified-id}}
|
||||
x->~int(); // expected-error{{expected the class name}}
|
||||
x->operator; // expected-error{{missing type specifier after 'operator'}}
|
||||
x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue