[cfe-commits] r90161 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/ExprCXX.h include/clang/AST/Stmt.h include/clang/AST/StmtNodes.def include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/Lookup.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/SemaCXX/qual-id-test.cpp test/SemaTemplate/instantiate-method.cpp
John McCall
rjmccall at apple.com
Mon Nov 30 14:42:36 PST 2009
Author: rjmccall
Date: Mon Nov 30 16:42:35 2009
New Revision: 90161
URL: http://llvm.org/viewvc/llvm-project?rev=90161&view=rev
Log:
Eliminate the use of OverloadedFunctionDecl in member expressions.
Create a new UnresolvedMemberExpr for these lookups. Assorted hackery
around qualified member expressions; this will all go away when we
implement the correct (i.e. extremely delayed) implicit-member semantics.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/Stmt.h
cfe/trunk/include/clang/AST/StmtNodes.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/Sema/Lookup.h
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaCXX/qual-id-test.cpp
cfe/trunk/test/SemaTemplate/instantiate-method.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Nov 30 16:42:35 2009
@@ -73,6 +73,8 @@
return false;
}
+ unsigned size() const { return Decls.size(); }
+
typedef DeclsTy::const_iterator iterator;
iterator begin() const { return Decls.begin(); }
iterator end() const { return Decls.end(); }
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Nov 30 16:42:35 2009
@@ -1617,6 +1617,179 @@
virtual child_iterator child_end();
};
+/// \brief Represents a C++ member access expression for which lookup
+/// produced a set of overloaded functions. These are replaced with
+/// MemberExprs in the final AST.
+class UnresolvedMemberExpr : public Expr {
+ /// The results. These are undesugared, which is to say, they may
+ /// include UsingShadowDecls.
+ UnresolvedSet Results;
+
+ /// \brief The expression for the base pointer or class reference,
+ /// e.g., the \c x in x.f.
+ Stmt *Base;
+
+ /// \brief Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ bool IsArrow : 1;
+
+ /// \brief Whether the lookup results contain an unresolved using
+ /// declaration.
+ bool HasUnresolvedUsing : 1;
+
+ /// \brief Whether this member expression has explicitly-specified template
+ /// arguments.
+ bool HasExplicitTemplateArgs : 1;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The nested-name-specifier that precedes the member name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The source range covering the nested name specifier.
+ SourceRange QualifierRange;
+
+ /// \brief The member to which this member expression refers, which
+ /// can be a name or an overloaded operator.
+ DeclarationName MemberName;
+
+ /// \brief The location of the member name.
+ SourceLocation MemberLoc;
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ ExplicitTemplateArgumentList *getExplicitTemplateArgs() {
+ assert(HasExplicitTemplateArgs);
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
+ return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs();
+ }
+
+ UnresolvedMemberExpr(QualType T, bool Dependent,
+ bool HasUnresolvedUsing,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName Member,
+ SourceLocation MemberLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+public:
+ static UnresolvedMemberExpr *
+ Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName Member,
+ SourceLocation MemberLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ /// Adds a declaration to the unresolved set. By assumption, all of
+ /// these happen at initialization time and properties like
+ /// 'Dependent' and 'HasUnresolvedUsing' take them into account.
+ void addDecl(NamedDecl *Decl) {
+ Results.addDecl(Decl);
+ }
+
+ typedef UnresolvedSet::iterator decls_iterator;
+ decls_iterator decls_begin() const { return Results.begin(); }
+ decls_iterator decls_end() const { return Results.end(); }
+
+ unsigned getNumDecls() const { return Results.size(); }
+
+ /// \brief Retrieve the base object of this member expressions,
+ /// e.g., the \c x in \c x.m.
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *E) { Base = E; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Retrieve the source range covering the nested-name-specifier
+ /// that qualifies the member name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMemberName() const { return MemberName; }
+ void setMemberName(DeclarationName N) { MemberName = N; }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgs() const {
+ return HasExplicitTemplateArgs;
+ }
+
+ /// \brief Copies the template arguments into the given structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ getExplicitTemplateArgs()->copyInto(List);
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following
+ /// the member name ('<').
+ SourceLocation getLAngleLoc() const {
+ return getExplicitTemplateArgs()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return getExplicitTemplateArgs()->getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as
+ /// part of this template-id.
+ unsigned getNumTemplateArgs() const {
+ return getExplicitTemplateArgs()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket
+ /// following the template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ return getExplicitTemplateArgs()->RAngleLoc;
+ }
+
+ virtual SourceRange getSourceRange() const {
+ SourceRange Range = Base->getSourceRange();
+ if (hasExplicitTemplateArgs())
+ Range.setEnd(getRAngleLoc());
+ else
+ Range.setEnd(MemberLoc);
+ return Range;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedMemberExprClass;
+ }
+ static bool classof(const UnresolvedMemberExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Nov 30 16:42:35 2009
@@ -171,6 +171,14 @@
}
virtual ~Stmt() {}
+#ifndef NDEBUG
+ /// \brief True if this statement's refcount is in a valid state.
+ /// Should be used only in assertions.
+ bool isRetained() const {
+ return (RefCount >= 1);
+ }
+#endif
+
/// \brief Destroy the current statement and its children.
void Destroy(ASTContext &Ctx) {
assert(RefCount >= 1);
Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Nov 30 16:42:35 2009
@@ -133,6 +133,7 @@
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
EXPR(CXXUnresolvedConstructExpr, Expr)
EXPR(CXXDependentScopeMemberExpr, Expr)
+EXPR(UnresolvedMemberExpr , Expr)
// Obj-C Expressions.
EXPR(ObjCStringLiteral , Expr)
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 30 16:42:35 2009
@@ -2085,6 +2085,8 @@
"inherited virtual base class">;
def err_not_direct_base_or_virtual : Error<
"type %0 is not a direct or virtual base of '%1'">;
+def err_not_direct_base_or_virtual_multi : Error<
+ "type %0 is not a direct or virtual base of '%1'">;
def err_in_class_initializer_non_integral_type : Error<
"in-class initializer has non-integral, non-enumeration type %0">;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Nov 30 16:42:35 2009
@@ -1525,6 +1525,7 @@
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
case Expr::CXXDependentScopeMemberExprClass:
+ case Expr::UnresolvedMemberExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCMessageExprClass:
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Nov 30 16:42:35 2009
@@ -573,3 +573,52 @@
Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() {
return child_iterator(&Base + 1);
}
+
+UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent,
+ bool HasUnresolvedUsing,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ const TemplateArgumentListInfo *TemplateArgs)
+ : Expr(UnresolvedMemberExprClass, T, Dependent, Dependent),
+ Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
+ HasExplicitTemplateArgs(TemplateArgs != 0),
+ OperatorLoc(OperatorLoc),
+ Qualifier(Qualifier), QualifierRange(QualifierRange),
+ MemberName(MemberName), MemberLoc(MemberLoc) {
+ if (TemplateArgs)
+ getExplicitTemplateArgs()->initializeFrom(*TemplateArgs);
+}
+
+UnresolvedMemberExpr *
+UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
+ bool HasUnresolvedUsing,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName Member,
+ SourceLocation MemberLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ std::size_t size = sizeof(UnresolvedMemberExpr);
+ if (TemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>());
+ return new (Mem) UnresolvedMemberExpr(
+ Dependent ? C.DependentTy : C.OverloadTy,
+ Dependent, HasUnresolvedUsing, Base, IsArrow,
+ OperatorLoc, Qualifier, QualifierRange,
+ Member, MemberLoc, TemplateArgs);
+}
+
+Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
+ return child_iterator(&Base);
+}
+
+Stmt::child_iterator UnresolvedMemberExpr::child_end() {
+ return child_iterator(&Base + 1);
+}
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Nov 30 16:42:35 2009
@@ -1163,6 +1163,24 @@
}
}
+void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+
+ // FIXME: this might originally have been written with 'template'
+
+ OS << Node->getMemberName().getAsString();
+
+ if (Node->hasExplicitTemplateArgs()) {
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+ }
+}
+
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Mon Nov 30 16:42:35 2009
@@ -558,6 +558,19 @@
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getMember());
+ ID.AddBoolean(S->hasExplicitTemplateArgumentList());
+ if (S->hasExplicitTemplateArgumentList())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isArrow());
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitName(S->getMemberName());
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {
Modified: cfe/trunk/lib/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Lookup.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Mon Nov 30 16:42:35 2009
@@ -213,6 +213,10 @@
return getResultKind() == FoundOverloaded;
}
+ bool isUnresolvableResult() const {
+ return getResultKind() == FoundUnresolvedValue;
+ }
+
LookupResultKind getResultKind() const {
sanity();
return ResultKind;
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Nov 30 16:42:35 2009
@@ -459,13 +459,20 @@
virtual void DeleteExpr(ExprTy *E);
virtual void DeleteStmt(StmtTy *S);
- OwningExprResult Owned(Expr* E) { return OwningExprResult(*this, E); }
+ OwningExprResult Owned(Expr* E) {
+ assert(!E || E->isRetained());
+ return OwningExprResult(*this, E);
+ }
OwningExprResult Owned(ExprResult R) {
if (R.isInvalid())
return ExprError();
+ assert(!R.get() || ((Expr*) R.get())->isRetained());
return OwningExprResult(*this, R.get());
}
- OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
+ OwningStmtResult Owned(Stmt* S) {
+ assert(!S || S->isRetained());
+ return OwningStmtResult(*this, S);
+ }
virtual void ActOnEndOfTranslationUnit();
@@ -516,7 +523,7 @@
/// \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);
+ DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name);
static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
@@ -1517,31 +1524,40 @@
ExprArg Idx,
SourceLocation RLoc);
- OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+ OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- DeclarationName MemberName,
- DeclPtrTy ImplDecl,
- const CXXScopeSpec *SS = 0,
- NamedDecl *FirstQualifierInScope = 0) {
- // FIXME: Temporary helper while we migrate existing calls to
- // BuildMemberReferenceExpr to support explicitly-specified template
- // arguments.
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
- MemberName, 0, ImplDecl, SS,
- FirstQualifierInScope);
- }
+ bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
- OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+ OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclPtrTy ObjCImpDecl);
+
+ bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const LookupResult &R);
+
+ OwningExprResult ActOnDependentMemberExpr(ExprArg Base,
+ bool IsArrow,
SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- DeclarationName MemberName,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
- DeclPtrTy ImplDecl,
- const CXXScopeSpec *SS,
- NamedDecl *FirstQualifierInScope = 0);
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
@@ -2140,9 +2156,7 @@
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
- bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
- SourceLocation NameLoc, QualType &ThisType,
- QualType &MemberType);
+ bool isImplicitMemberReference(const LookupResult &R, QualType &ThisType);
//===--------------------------------------------------------------------===//
// C++ Derived Classes
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 30 16:42:35 2009
@@ -1757,7 +1757,7 @@
}
/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
-DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
+DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
return DeclarationName(Name.Identifier);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Nov 30 16:42:35 2009
@@ -617,7 +617,54 @@
return Owned(Result);
}
-static void DecomposeTemplateName(LookupResult &R, TemplateName TName) {
+/// Decomposes the given name into a DeclarationName, its location, and
+/// possibly a list of template arguments.
+///
+/// If this produces template arguments, it is permitted to call
+/// DecomposeTemplateName.
+///
+/// This actually loses a lot of source location information for
+/// non-standard name kinds; we should consider preserving that in
+/// some way.
+static void DecomposeUnqualifiedId(Sema &SemaRef,
+ const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationName &Name,
+ SourceLocation &NameLoc,
+ const TemplateArgumentListInfo *&TemplateArgs) {
+ if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+ Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
+ Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
+ ASTTemplateArgsPtr TemplateArgsPtr(SemaRef,
+ Id.TemplateId->getTemplateArgs(),
+ Id.TemplateId->NumArgs);
+ SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer);
+ TemplateArgsPtr.release();
+
+ TemplateName TName =
+ Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
+ Name = SemaRef.Context.getNameForTemplate(TName);
+ NameLoc = Id.TemplateId->TemplateNameLoc;
+ TemplateArgs = &Buffer;
+ } else {
+ Name = SemaRef.GetNameFromUnqualifiedId(Id);
+ NameLoc = Id.StartLocation;
+ TemplateArgs = 0;
+ }
+}
+
+/// Decompose the given template name into a list of lookup results.
+///
+/// The unqualified ID must name a non-dependent template, which can
+/// be more easily tested by checking whether DecomposeUnqualifiedId
+/// found template arguments.
+static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) {
+ assert(Id.getKind() == UnqualifiedId::IK_TemplateId);
+ TemplateName TName =
+ Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
if (TemplateDecl *TD = TName.getAsTemplateDecl())
R.addDecl(TD);
else if (OverloadedFunctionDecl *OD
@@ -628,6 +675,42 @@
R.resolveKind();
}
+static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
+ for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+ E = Record->bases_end(); I != E; ++I) {
+ CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+ CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+ if (!BaseRT) return false;
+
+ CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+ if (!BaseRecord->isDefinition() ||
+ !IsFullyFormedScope(SemaRef, BaseRecord))
+ return false;
+ }
+
+ return true;
+}
+
+/// Determines whether the given scope is "fully-formed": i.e. we can
+/// look into it because it's either non-dependent or is the current
+/// instantiation and has no dependent base classes.
+static bool IsFullyFormedScope(Sema &SemaRef, const CXXScopeSpec &SS) {
+ DeclContext *DC = SemaRef.computeDeclContext(SS, false);
+ if (!DC) return false;
+ if (!DC->isDependentContext()) return true;
+ return IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC));
+}
+
+static bool IsFullyFormedScope(Sema &SemaRef, DeclContext *DC) {
+ if (isa<CXXMethodDecl>(DC))
+ return IsFullyFormedScope(SemaRef,
+ cast<CXXRecordDecl>(cast<CXXMethodDecl>(DC)->getParent()));
+ else if (isa<CXXRecordDecl>(DC))
+ return IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC));
+ else
+ return true;
+}
+
Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Id,
@@ -639,33 +722,14 @@
if (SS.isInvalid())
return ExprError();
- TemplateArgumentListInfo ExplicitTemplateArgs;
+ TemplateArgumentListInfo TemplateArgsBuffer;
// Decompose the UnqualifiedId into the following data.
DeclarationName Name;
SourceLocation NameLoc;
const TemplateArgumentListInfo *TemplateArgs;
- if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
- ExplicitTemplateArgs.setLAngleLoc(Id.TemplateId->LAngleLoc);
- ExplicitTemplateArgs.setRAngleLoc(Id.TemplateId->RAngleLoc);
-
- ASTTemplateArgsPtr TemplateArgsPtr(*this,
- Id.TemplateId->getTemplateArgs(),
- Id.TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs);
- TemplateArgsPtr.release();
-
- TemplateName TName =
- TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
- Name = Context.getNameForTemplate(TName);
- NameLoc = Id.TemplateId->TemplateNameLoc;
- TemplateArgs = &ExplicitTemplateArgs;
- } else {
- Name = GetNameFromUnqualifiedId(Id);
- NameLoc = Id.StartLocation;
- TemplateArgs = 0;
- }
+ DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+ Name, NameLoc, TemplateArgs);
IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -675,7 +739,8 @@
// names a dependent type.
// Determine whether this is a member of an unknown specialization;
// we need to handle these differently.
- if (SS.isSet() && !computeDeclContext(SS, false)) {
+ if (SS.isSet() && !(IsFullyFormedScope(*this, SS) &&
+ IsFullyFormedScope(*this, CurContext))) {
bool CheckForImplicitMember = !isAddressOfOperand;
return ActOnDependentIdExpression(SS, Name, NameLoc,
@@ -686,11 +751,8 @@
// Perform the required lookup.
LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
if (TemplateArgs) {
- TemplateName TName =
- TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
// Just re-use the lookup done by isTemplateName.
- DecomposeTemplateName(R, TName);
+ DecomposeTemplateName(R, Id);
} else {
LookupParsedName(R, S, &SS, true);
@@ -806,9 +868,10 @@
return BuildDeclarationNameExpr(SS, R, ADL);
}
-/// ActOnDeclarationNameExpr - Build a C++ qualified declaration name,
-/// generally during template instantiation. There's a large number
-/// of things which don't need to be done along this path.
+/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
+/// declaration name, generally during template instantiation.
+/// There's a large number of things which don't need to be done along
+/// this path.
Sema::OwningExprResult
Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
DeclarationName Name,
@@ -959,20 +1022,42 @@
/// \brief Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
- const CXXScopeSpec *SS, NamedDecl *Member,
+ const CXXScopeSpec &SS, NamedDecl *Member,
SourceLocation Loc, QualType Ty,
const TemplateArgumentListInfo *TemplateArgs = 0) {
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
- if (SS && SS->isSet()) {
- Qualifier = (NestedNameSpecifier *) SS->getScopeRep();
- QualifierRange = SS->getRange();
+ if (SS.isSet()) {
+ Qualifier = (NestedNameSpecifier *) SS.getScopeRep();
+ QualifierRange = SS.getRange();
}
return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
Member, Loc, TemplateArgs, Ty);
}
+/// Return true if all the decls in the given result are instance
+/// methods.
+static bool IsOnlyInstanceMethods(const LookupResult &R) {
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+
+ CXXMethodDecl *Method;
+ if (isa<FunctionTemplateDecl>(D))
+ Method = cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D)
+ ->getTemplatedDecl());
+ else if (isa<CXXMethodDecl>(D))
+ Method = cast<CXXMethodDecl>(D);
+ else
+ return false;
+
+ if (Method->isStatic())
+ return false;
+ }
+
+ return true;
+}
+
/// Builds an implicit member access expression from the given
/// unqualified lookup set, which is known to contain only class
/// members.
@@ -982,50 +1067,35 @@
const TemplateArgumentListInfo *TemplateArgs) {
assert(!R.empty() && !R.isAmbiguous());
- NamedDecl *D = R.getAsSingleDecl(Context);
SourceLocation Loc = R.getNameLoc();
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
// FIXME: This needs to happen post-isImplicitMemberReference?
// FIXME: template-ids inside anonymous structs?
- if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
+ if (FieldDecl *FD = R.getAsSingle<FieldDecl>())
if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
return BuildAnonymousStructUnionMemberReference(Loc, FD);
QualType ThisType;
- QualType MemberType;
- if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) {
+ if (isImplicitMemberReference(R, ThisType)) {
Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
- MarkDeclarationReferenced(Loc, D);
- if (PerformObjectMemberConversion(This, D))
- return ExprError();
-
- bool ShouldCheckUse = true;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- // Don't diagnose the use of a virtual member function unless it's
- // explicitly qualified.
- if (MD->isVirtual() && !SS.isSet())
- ShouldCheckUse = false;
- }
-
- if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
- return ExprError();
- return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType,
- TemplateArgs));
+ return BuildMemberReferenceExpr(ExprArg(*this, This),
+ /*OpLoc*/ SourceLocation(),
+ /*IsArrow*/ true,
+ SS, R, TemplateArgs);
}
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- if (!Method->isStatic())
- return ExprError(Diag(Loc, diag::err_member_call_without_object));
- }
+ // Diagnose now if none of the available methods are static.
+ if (IsOnlyInstanceMethods(R))
+ return ExprError(Diag(Loc, diag::err_member_call_without_object));
- if (isa<FieldDecl>(D)) {
+ if (R.getAsSingle<FieldDecl>()) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (MD->isStatic()) {
// "invalid use of member 'x' in static member function"
Diag(Loc, diag::err_invalid_member_use_in_static_method)
- << D->getDeclName();
+ << R.getLookupName();
return ExprError();
}
}
@@ -1034,7 +1104,7 @@
// program would have been turned into implicit member expressions
// above.
Diag(Loc, diag::err_invalid_non_static_member_use)
- << D->getDeclName();
+ << R.getLookupName();
return ExprError();
}
@@ -1876,29 +1946,318 @@
return GDecl;
}
-Action::OwningExprResult
-Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, SourceLocation MemberLoc,
- DeclarationName MemberName,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
- DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS,
- NamedDecl *FirstQualifierInScope) {
- if (SS && SS->isInvalid())
+Sema::OwningExprResult
+Sema::ActOnDependentMemberExpr(ExprArg Base, bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclarationName Name, SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ Expr *BaseExpr = Base.takeAs<Expr>();
+
+ // Even in dependent contexts, try to diagnose base expressions with
+ // obviously wrong types, e.g.:
+ //
+ // T* t;
+ // t.f;
+ //
+ // In Obj-C++, however, the above expression is valid, since it could be
+ // accessing the 'f' property if T is an Obj-C interface. The extra check
+ // allows this, while still reporting an error if T is a struct pointer.
+ if (!IsArrow) {
+ const PointerType *PT = BaseExpr->getType()->getAs<PointerType>();
+ if (PT && (!getLangOptions().ObjC1 ||
+ PT->getPointeeType()->isRecordType())) {
+ Diag(NameLoc, diag::err_typecheck_member_reference_struct_union)
+ << BaseExpr->getType() << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+ }
+
+ assert(BaseExpr->getType()->isDependentType());
+
+ // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
+ // must have pointer type, and the accessed type is the pointee.
+ return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr,
+ IsArrow, OpLoc,
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getRange(),
+ FirstQualifierInScope,
+ Name, NameLoc,
+ TemplateArgs));
+}
+
+/// We know that the given qualified member reference points only to
+/// declarations which do not belong to the static type of the base
+/// expression. Diagnose the problem.
+static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
+ Expr *BaseExpr,
+ QualType BaseType,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const LookupResult &R) {
+ DeclContext *DC = R.getRepresentativeDecl()->getDeclContext();
+
+ // FIXME: this is an exceedingly lame diagnostic for some of the more
+ // complicated cases here.
+ SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual)
+ << QualifierRange << DC << BaseType;
+}
+
+// Check whether the declarations we found through a nested-name
+// specifier in a member expression are actually members of the base
+// type. The restriction here is:
+//
+// C++ [expr.ref]p2:
+// ... In these cases, the id-expression shall name a
+// member of the class or of one of its base classes.
+//
+// So it's perfectly legitimate for the nested-name specifier to name
+// an unrelated class, and for us to find an overload set including
+// decls from classes which are not superclasses, as long as the decl
+// we actually pick through overload resolution is from a superclass.
+bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
+ QualType BaseType,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const LookupResult &R) {
+ QualType BaseTypeCanon
+ = Context.getCanonicalType(BaseType).getUnqualifiedType();
+
+ bool FoundValid = false;
+
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ TypeDecl* TyD = cast<TypeDecl>((*I)->getUnderlyingDecl()->getDeclContext());
+ CanQualType MemberTypeCanon
+ = Context.getCanonicalType(Context.getTypeDeclType(TyD));
+
+ if (BaseTypeCanon == MemberTypeCanon ||
+ IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) {
+ FoundValid = true;
+ break;
+ }
+ }
+
+ if (!FoundValid) {
+ DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType,
+ Qualifier, QualifierRange, R);
+ return true;
+ }
+
+ return false;
+}
+
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg BaseArg,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclarationName Name, SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ Expr *Base = BaseArg.takeAs<Expr>();
+
+ if (Base->getType()->isDependentType())
+ return ActOnDependentMemberExpr(ExprArg(*this, Base),
+ IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ Name, NameLoc,
+ TemplateArgs);
+
+ LookupResult R(*this, Name, NameLoc, LookupMemberName);
+ OwningExprResult Result =
+ LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ /*ObjCImpDecl*/ DeclPtrTy());
+
+ if (Result.isInvalid()) {
+ Owned(Base);
return ExprError();
+ }
- // Since this might be a postfix expression, get rid of ParenListExprs.
- Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+ if (Result.get())
+ return move(Result);
+
+ return BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc,
+ IsArrow, SS, R, TemplateArgs);
+}
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg Base, SourceLocation OpLoc,
+ bool IsArrow, const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
Expr *BaseExpr = Base.takeAs<Expr>();
+ QualType BaseType = BaseExpr->getType();
+ if (IsArrow) {
+ assert(BaseType->isPointerType());
+ BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+ }
+
+ NestedNameSpecifier *Qualifier =
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ DeclarationName MemberName = R.getLookupName();
+ SourceLocation MemberLoc = R.getNameLoc();
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ // Rederive where we looked up.
+ DeclContext *DC = (SS.isSet()
+ ? computeDeclContext(SS, false)
+ : BaseType->getAs<RecordType>()->getDecl());
+
+ Diag(R.getNameLoc(), diag::err_no_member)
+ << MemberName << DC << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+
+ // We can't always diagnose the problem yet: it's permitted for
+ // lookup to find things from an invalid context as long as they
+ // don't get picked by overload resolution.
+ if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType,
+ Qualifier, SS.getRange(), R))
+ return ExprError();
+
+ // Construct an unresolved result if we in fact got an unresolved
+ // result.
+ if (R.isOverloadedResult() || R.isUnresolvableResult()) {
+ bool Dependent = R.isUnresolvableResult();
+ Dependent = Dependent ||
+ UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
+ TemplateArgs);
+
+ UnresolvedMemberExpr *MemExpr
+ = UnresolvedMemberExpr::Create(Context, Dependent,
+ R.isUnresolvableResult(),
+ BaseExpr, IsArrow, OpLoc,
+ Qualifier, SS.getRange(),
+ MemberName, MemberLoc,
+ TemplateArgs);
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ MemExpr->addDecl(*I);
+
+ return Owned(MemExpr);
+ }
+
+ assert(R.isSingleResult());
+ NamedDecl *MemberDecl = R.getFoundDecl();
+
+ // FIXME: diagnose the presence of template arguments now.
+
+ // If the decl being referenced had an error, return an error for this
+ // sub-expr without emitting another error, in order to avoid cascading
+ // error cases.
+ if (MemberDecl->isInvalidDecl())
+ return ExprError();
+
+ bool ShouldCheckUse = true;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+ // Don't diagnose the use of a virtual member function unless it's
+ // explicitly qualified.
+ if (MD->isVirtual() && !SS.isSet())
+ ShouldCheckUse = false;
+ }
+
+ // Check the use of this member.
+ if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
+ Owned(BaseExpr);
+ return ExprError();
+ }
+
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
+ // We may have found a field within an anonymous union or struct
+ // (C++ [class.union]).
+ if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
+ return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
+ BaseExpr, OpLoc);
+
+ // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
+ QualType MemberType = FD->getType();
+ if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
+ MemberType = Ref->getPointeeType();
+ else {
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+ BaseQuals.removeObjCGCAttr();
+ if (FD->isMutable()) BaseQuals.removeConst();
+
+ Qualifiers MemberQuals
+ = Context.getCanonicalType(MemberType).getQualifiers();
+
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ MemberType = Context.getQualifiedType(MemberType, Combined);
+ }
+
+ MarkDeclarationReferenced(MemberLoc, FD);
+ if (PerformObjectMemberConversion(BaseExpr, FD))
+ return ExprError();
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ FD, MemberLoc, MemberType));
+ }
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, Var);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ Var, MemberLoc,
+ Var->getType().getNonReferenceType()));
+ }
+
+ if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ MemberFn, MemberLoc,
+ MemberFn->getType()));
+ }
+
+ if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ Enum, MemberLoc, Enum->getType()));
+ }
+
+ Owned(BaseExpr);
+
+ if (isa<TypeDecl>(MemberDecl))
+ return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
+ << MemberName << int(IsArrow));
+
+ // We found a declaration kind that we didn't expect. This is a
+ // generic error message that tells the user that she can't refer
+ // to this member with '.' or '->'.
+ return ExprError(Diag(MemberLoc,
+ diag::err_typecheck_member_reference_unknown)
+ << MemberName << int(IsArrow));
+}
+
+/// Look up the given member of the given non-type-dependent
+/// expression. This can return in one of two ways:
+/// * If it returns a sentinel null-but-valid result, the caller will
+/// assume that lookup was performed and the results written into
+/// the provided structure. It will take over from there.
+/// * Otherwise, the returned expression will be produced in place of
+/// an ordinary member expression.
+///
+/// The ObjCImpDecl bit is a gross hack that will need to be properly
+/// fixed for ObjC++.
+Sema::OwningExprResult
+Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ DeclPtrTy ObjCImpDecl) {
assert(BaseExpr && "no base expression");
// Perform default conversions.
DefaultFunctionArrayConversion(BaseExpr);
QualType BaseType = BaseExpr->getType();
+ assert(!BaseType->isDependentType());
+
+ DeclarationName MemberName = R.getLookupName();
+ SourceLocation MemberLoc = R.getNameLoc();
// If the user is trying to apply -> or . to a function pointer
- // type, it's probably because the forgot parentheses to call that
+ // type, it's probably because they forgot parentheses to call that
// function. Suggest the addition of those parentheses, build the
// call, and continue on.
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
@@ -1906,8 +2265,8 @@
= Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
QualType ResultTy = Fun->getResultType();
if (Fun->getNumArgs() == 0 &&
- ((OpKind == tok::period && ResultTy->isRecordType()) ||
- (OpKind == tok::arrow && ResultTy->isPointerType() &&
+ ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
ResultTy->getAs<PointerType>()->getPointeeType()
->isRecordType()))) {
SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
@@ -1916,10 +2275,10 @@
<< CodeModificationHint::CreateInsertion(Loc, "()");
OwningExprResult NewBase
- = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc,
+ = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc,
MultiExprArg(*this, 0, 0), 0, Loc);
if (NewBase.isInvalid())
- return move(NewBase);
+ return ExprError();
BaseExpr = NewBase.takeAs<Expr>();
DefaultFunctionArrayConversion(BaseExpr);
@@ -1938,6 +2297,7 @@
ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
}
}
+
// If this is an Objective-C pseudo-builtin and a definition is provided then
// use that.
if (Context.isObjCSelType(BaseType)) {
@@ -1948,10 +2308,11 @@
ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
}
}
+
assert(!BaseType.isNull() && "no type for member expression");
// Handle properties on ObjC 'Class' types.
- if (OpKind == tok::period && BaseType->isObjCClassType()) {
+ if (!IsArrow && BaseType->isObjCClassType()) {
// Also must look for a getter name which uses property syntax.
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
@@ -2005,68 +2366,21 @@
BaseType = Context.ObjCClassRedefinitionType;
ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
}
-
- // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
- // must have pointer type, and the accessed type is the pointee.
- if (OpKind == tok::arrow) {
- if (BaseType->isDependentType()) {
- NestedNameSpecifier *Qualifier = 0;
- if (SS) {
- Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
- if (!FirstQualifierInScope)
- FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier);
- }
- return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, true,
- OpLoc, Qualifier,
- SS? SS->getRange() : SourceRange(),
- FirstQualifierInScope,
- MemberName,
- MemberLoc,
- ExplicitTemplateArgs));
- }
- else if (const PointerType *PT = BaseType->getAs<PointerType>())
+ if (IsArrow) {
+ if (const PointerType *PT = BaseType->getAs<PointerType>())
BaseType = PT->getPointeeType();
else if (BaseType->isObjCObjectPointerType())
;
- else
- return ExprError(Diag(MemberLoc,
- diag::err_typecheck_member_reference_arrow)
- << BaseType << BaseExpr->getSourceRange());
- } else if (BaseType->isDependentType()) {
- // Require that the base type isn't a pointer type
- // (so we'll report an error for)
- // T* t;
- // t.f;
- //
- // In Obj-C++, however, the above expression is valid, since it could be
- // accessing the 'f' property if T is an Obj-C interface. The extra check
- // allows this, while still reporting an error if T is a struct pointer.
- const PointerType *PT = BaseType->getAs<PointerType>();
-
- if (!PT || (getLangOptions().ObjC1 &&
- !PT->getPointeeType()->isRecordType())) {
- NestedNameSpecifier *Qualifier = 0;
- if (SS) {
- Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
- if (!FirstQualifierInScope)
- FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier);
- }
-
- return Owned(CXXDependentScopeMemberExpr::Create(Context,
- BaseExpr, false,
- OpLoc,
- Qualifier,
- SS? SS->getRange() : SourceRange(),
- FirstQualifierInScope,
- MemberName,
- MemberLoc,
- ExplicitTemplateArgs));
- }
+ else {
+ Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+ << BaseType << BaseExpr->getSourceRange();
+ return ExprError();
}
+ }
- // Handle field access to simple records. This also handles access to fields
- // of the ObjC 'id' struct.
+ // Handle field access to simple records. This also handles access
+ // to fields of the ObjC 'id' struct.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
RecordDecl *RDecl = RTy->getDecl();
if (RequireCompleteType(OpLoc, BaseType,
@@ -2075,14 +2389,14 @@
return ExprError();
DeclContext *DC = RDecl;
- if (SS && SS->isSet()) {
+ if (SS.isSet()) {
// If the member name was a qualified-id, look into the
// nested-name-specifier.
- DC = computeDeclContext(*SS, false);
+ DC = computeDeclContext(SS, false);
if (!isa<TypeDecl>(DC)) {
Diag(MemberLoc, diag::err_qualified_member_nonclass)
- << DC << SS->getRange();
+ << DC << SS.getRange();
return ExprError();
}
@@ -2092,135 +2406,8 @@
}
// The record definition is complete, now make sure the member is valid.
- LookupResult Result(*this, MemberName, MemberLoc, LookupMemberName);
- LookupQualifiedName(Result, DC);
-
- if (Result.empty())
- return ExprError(Diag(MemberLoc, diag::err_no_member)
- << MemberName << DC << BaseExpr->getSourceRange());
- if (Result.isAmbiguous())
- return ExprError();
-
- NamedDecl *MemberDecl = Result.getAsSingleDecl(Context);
-
- if (SS && SS->isSet()) {
- TypeDecl* TyD = cast<TypeDecl>(MemberDecl->getDeclContext());
- QualType BaseTypeCanon
- = Context.getCanonicalType(BaseType).getUnqualifiedType();
- QualType MemberTypeCanon
- = Context.getCanonicalType(Context.getTypeDeclType(TyD));
-
- if (BaseTypeCanon != MemberTypeCanon &&
- !IsDerivedFrom(BaseTypeCanon, MemberTypeCanon))
- return ExprError(Diag(SS->getBeginLoc(),
- diag::err_not_direct_base_or_virtual)
- << MemberTypeCanon << BaseTypeCanon);
- }
-
- // If the decl being referenced had an error, return an error for this
- // sub-expr without emitting another error, in order to avoid cascading
- // error cases.
- if (MemberDecl->isInvalidDecl())
- return ExprError();
-
- bool ShouldCheckUse = true;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
- // Don't diagnose the use of a virtual member function unless it's
- // explicitly qualified.
- if (MD->isVirtual() && (!SS || !SS->isSet()))
- ShouldCheckUse = false;
- }
-
- // Check the use of this field
- if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc))
- return ExprError();
-
- if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
- // We may have found a field within an anonymous union or struct
- // (C++ [class.union]).
- if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
- return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
- BaseExpr, OpLoc);
-
- // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
- QualType MemberType = FD->getType();
- if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
- MemberType = Ref->getPointeeType();
- else {
- Qualifiers BaseQuals = BaseType.getQualifiers();
- BaseQuals.removeObjCGCAttr();
- if (FD->isMutable()) BaseQuals.removeConst();
-
- Qualifiers MemberQuals
- = Context.getCanonicalType(MemberType).getQualifiers();
-
- Qualifiers Combined = BaseQuals + MemberQuals;
- if (Combined != MemberQuals)
- MemberType = Context.getQualifiedType(MemberType, Combined);
- }
-
- MarkDeclarationReferenced(MemberLoc, FD);
- if (PerformObjectMemberConversion(BaseExpr, FD))
- return ExprError();
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- FD, MemberLoc, MemberType));
- }
-
- if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- Var, MemberLoc,
- Var->getType().getNonReferenceType()));
- }
- if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- MemberFn, MemberLoc,
- MemberFn->getType()));
- }
- if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
-
- if (ExplicitTemplateArgs)
- return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
- (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
- SS? SS->getRange() : SourceRange(),
- FunTmpl, MemberLoc,
- ExplicitTemplateArgs,
- Context.OverloadTy));
-
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- FunTmpl, MemberLoc,
- Context.OverloadTy));
- }
- if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) {
- if (ExplicitTemplateArgs)
- return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
- (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
- SS? SS->getRange() : SourceRange(),
- Ovl, MemberLoc, ExplicitTemplateArgs,
- Context.OverloadTy));
-
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- Ovl, MemberLoc, Context.OverloadTy));
- }
- if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
- return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
- Enum, MemberLoc, Enum->getType()));
- }
- if (isa<TypeDecl>(MemberDecl))
- return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
- << MemberName << int(OpKind == tok::arrow));
-
- // We found a declaration kind that we didn't expect. This is a
- // generic error message that tells the user that she can't refer
- // to this member with '.' or '->'.
- return ExprError(Diag(MemberLoc,
- diag::err_typecheck_member_reference_unknown)
- << MemberName << int(OpKind == tok::arrow));
+ LookupQualifiedName(R, DC);
+ return Owned((Expr*) 0);
}
// Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring
@@ -2256,18 +2443,17 @@
// FIXME: We've lost the precise spelling of the type by going through
// DeclarationName. Can we do better?
return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
- OpKind == tok::arrow,
- OpLoc,
- (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
- SS? SS->getRange() : SourceRange(),
+ IsArrow, OpLoc,
+ (NestedNameSpecifier *) SS.getScopeRep(),
+ SS.getRange(),
MemberName.getCXXNameType(),
MemberLoc));
}
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
// (*Obj).ivar.
- if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) ||
- (OpKind == tok::period && BaseType->isObjCInterfaceType())) {
+ if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCInterfaceType())) {
const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>();
const ObjCInterfaceType *IFaceT =
OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>();
@@ -2322,7 +2508,7 @@
return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
MemberLoc, BaseExpr,
- OpKind == tok::arrow));
+ IsArrow));
}
return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
<< IDecl->getDeclName() << MemberName
@@ -2330,8 +2516,8 @@
}
}
// Handle properties on 'id' and qualified "id".
- if (OpKind == tok::period && (BaseType->isObjCIdType() ||
- BaseType->isObjCQualifiedIdType())) {
+ if (!IsArrow && (BaseType->isObjCIdType() ||
+ BaseType->isObjCQualifiedIdType())) {
const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
@@ -2364,8 +2550,7 @@
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
const ObjCObjectPointerType *OPT;
- if (OpKind == tok::period &&
- (OPT = BaseType->getAsObjCInterfacePointerType())) {
+ if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) {
const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
ObjCInterfaceDecl *IFace = IFaceT->getDecl();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
@@ -2450,7 +2635,7 @@
}
// Handle the following exceptional case (*Obj).isa.
- if (OpKind == tok::period &&
+ if (!IsArrow &&
BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) &&
MemberName.getAsIdentifierInfo()->isStr("isa"))
return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc,
@@ -2472,74 +2657,105 @@
return ExprError();
}
-Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+static Sema::OwningExprResult DiagnoseDtorReference(Sema &SemaRef,
+ SourceLocation NameLoc,
+ Sema::ExprArg MemExpr) {
+ Expr *E = (Expr *) MemExpr.get();
+ SourceLocation ExpectedLParenLoc = SemaRef.PP.getLocForEndOfToken(NameLoc);
+ SemaRef.Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
+ << isa<CXXPseudoDestructorExpr>(E)
+ << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
+
+ return SemaRef.ActOnCallExpr(/*Scope*/ 0,
+ move(MemExpr),
+ /*LPLoc*/ ExpectedLParenLoc,
+ Sema::MultiExprArg(SemaRef, 0, 0),
+ /*CommaLocs*/ 0,
+ /*RPLoc*/ ExpectedLParenLoc);
+}
+
+/// The main callback when the parser finds something like
+/// expression . [nested-name-specifier] identifier
+/// expression -> [nested-name-specifier] identifier
+/// where 'identifier' encompasses a fairly broad spectrum of
+/// possibilities, including destructor and operator references.
+///
+/// \param OpKind either tok::arrow or tok::period
+/// \param HasTrailingLParen whether the next token is '(', which
+/// is used to diagnose mis-uses of special members that can
+/// only be called
+/// \param ObjCImpDecl the current ObjC @implementation decl;
+/// this is an ugly hack around the fact that ObjC @implementations
+/// aren't properly put in the context chain
+Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
SourceLocation OpLoc,
tok::TokenKind OpKind,
const CXXScopeSpec &SS,
- UnqualifiedId &Member,
+ UnqualifiedId &Id,
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 {
- DependentTemplateName *DTN = Template.getAsDependentTemplateName();
- if (DTN->isIdentifier())
- Name = DTN->getIdentifier();
- else
- Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ if (SS.isSet() && SS.isInvalid())
+ return ExprError();
+
+ TemplateArgumentListInfo TemplateArgsBuffer;
+
+ // Decompose the name into its component parts.
+ DeclarationName Name;
+ SourceLocation NameLoc;
+ const TemplateArgumentListInfo *TemplateArgs;
+ DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+ Name, NameLoc, TemplateArgs);
+
+ bool IsArrow = (OpKind == tok::arrow);
+
+ NamedDecl *FirstQualifierInScope
+ = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+
+ // This is a postfix expression, so get rid of ParenListExprs.
+ BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg));
+
+ Expr *Base = BaseArg.takeAs<Expr>();
+ OwningExprResult Result(*this);
+ if (Base->getType()->isDependentType()) {
+ Result = ActOnDependentMemberExpr(ExprArg(*this, Base),
+ IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ Name, NameLoc,
+ TemplateArgs);
+ } else {
+ LookupResult R(*this, Name, NameLoc, LookupMemberName);
+ if (TemplateArgs) {
+ // Re-use the lookup done for the template name.
+ DecomposeTemplateName(R, Id);
+ } else {
+ Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ ObjCImpDecl);
+
+ if (Result.isInvalid()) {
+ Owned(Base);
+ return ExprError();
+ }
+
+ if (Result.get()) {
+ // The only way a reference to a destructor can be used is to
+ // immediately call it, which falls into this case. If the
+ // next token is not a '(', produce a diagnostic and build the
+ // call now.
+ if (!HasTrailingLParen &&
+ Id.getKind() == UnqualifiedId::IK_DestructorName)
+ return DiagnoseDtorReference(*this, NameLoc, move(Result));
+
+ return move(Result);
+ }
}
-
- // Translate the parser's template argument list in our AST format.
- ASTTemplateArgsPtr TemplateArgsPtr(*this,
- Member.TemplateId->getTemplateArgs(),
- Member.TemplateId->NumArgs);
-
- TemplateArgumentListInfo TemplateArgs;
- TemplateArgs.setLAngleLoc(Member.TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(Member.TemplateId->RAngleLoc);
- translateTemplateArguments(TemplateArgsPtr, 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, &TemplateArgs, DeclPtrTy(),
- &SS);
+
+ Result = BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc,
+ IsArrow, SS, R, TemplateArgs);
}
-
- // 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);
+
+ return move(Result);
}
Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -2820,20 +3036,32 @@
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
CommaLocs, RParenLoc));
+ Expr *NakedFn = Fn->IgnoreParens();
+
+ // Determine whether this is a call to an unresolved member function.
+ if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ // If lookup was unresolved but not dependent (i.e. didn't find
+ // an unresolved using declaration), it has to be an overloaded
+ // function set, which means it must contain either multiple
+ // declarations (all methods or method templates) or a single
+ // method template.
+ assert((MemE->getNumDecls() > 1) ||
+ isa<FunctionTemplateDecl>(*MemE->decls_begin()));
+
+ return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+ CommaLocs, RParenLoc));
+ }
+
// Determine whether this is a call to a member function.
- if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) {
+ if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
NamedDecl *MemDecl = MemExpr->getMemberDecl();
- if (isa<OverloadedFunctionDecl>(MemDecl) ||
- isa<CXXMethodDecl>(MemDecl) ||
- (isa<FunctionTemplateDecl>(MemDecl) &&
- isa<CXXMethodDecl>(
- cast<FunctionTemplateDecl>(MemDecl)->getTemplatedDecl())))
+ if (isa<CXXMethodDecl>(MemDecl))
return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
CommaLocs, RParenLoc));
}
// Determine whether this is a call to a pointer-to-member function.
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) {
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
if (BO->getOpcode() == BinaryOperator::PtrMemD ||
BO->getOpcode() == BinaryOperator::PtrMemI) {
if (const FunctionProtoType *FPT =
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 30 16:42:35 2009
@@ -2236,9 +2236,6 @@
///
/// FIXME: Should Objective-C also use this approach?
///
-/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the
-/// name of the declaration referenced.
-///
/// \param D the declaration being referenced from the current scope.
///
/// \param NameLoc the location of the name in the source.
@@ -2247,16 +2244,11 @@
/// access, will be set to the type of the "this" pointer to be used when
/// building that implicit member access.
///
-/// \param MemberType if the reference to this declaration is an implicit
-/// member access, will be set to the type of the member being referenced
-/// (for use at the type of the resulting member access expression).
-///
/// \returns true if this is an implicit member reference (in which case
/// \p ThisType and \p MemberType will be set), or false if it is not an
/// implicit member reference.
-bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
- SourceLocation NameLoc, QualType &ThisType,
- QualType &MemberType) {
+bool Sema::isImplicitMemberReference(const LookupResult &R,
+ QualType &ThisType) {
// If this isn't a C++ method, then it isn't an implicit member reference.
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
if (!MD || MD->isStatic())
@@ -2269,33 +2261,21 @@
// class member access expression (5.2.5) using (*this) (9.3.2)
// as the postfix-expression to the left of the '.' operator.
DeclContext *Ctx = 0;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ if (R.isUnresolvableResult()) {
+ // FIXME: this is just picking one at random
+ Ctx = R.getRepresentativeDecl()->getDeclContext();
+ } else if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) {
Ctx = FD->getDeclContext();
- MemberType = FD->getType();
-
- if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
- MemberType = RefType->getPointeeType();
- else if (!FD->isMutable())
- MemberType
- = Context.getQualifiedType(MemberType,
- Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
- } else if (isa<UnresolvedUsingValueDecl>(D)) {
- Ctx = D->getDeclContext();
- MemberType = Context.DependentTy;
} else {
- for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) {
- CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl);
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I);
FunctionTemplateDecl *FunTmpl = 0;
- if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
+ if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)))
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
// FIXME: Do we have to know if there are explicit template arguments?
if (Method && !Method->isStatic()) {
Ctx = Method->getParent();
- if (isa<CXXMethodDecl>(D) && !FunTmpl)
- MemberType = Method->getType();
- else
- MemberType = Context.OverloadTy;
break;
}
}
@@ -2307,6 +2287,8 @@
// Determine whether the declaration(s) we found are actually in a base
// class. If not, this isn't an implicit member reference.
ThisType = MD->getThisType(Context);
+
+ // FIXME: this doesn't really work for overloaded lookups.
QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
QualType ClassType
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Nov 30 16:42:35 2009
@@ -4341,9 +4341,7 @@
llvm::SmallVector<NamedDecl*,8> Fns;
- // Try to dig out the overloaded function.
- OverloadedFunctionDecl *Ovl = 0;
- FunctionTemplateDecl *FunctionTemplate = 0;
+ // Look into the overloaded expression.
if (UnresolvedLookupExpr *UL
= dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
Fns.append(UL->decls_begin(), UL->decls_end());
@@ -4351,17 +4349,15 @@
HasExplicitTemplateArgs = true;
UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
- } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
- Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
- FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
- HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
- if (HasExplicitTemplateArgs)
+ } else if (UnresolvedMemberExpr *ME
+ = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
+ Fns.append(ME->decls_begin(), ME->decls_end());
+ if (ME->hasExplicitTemplateArgs()) {
+ HasExplicitTemplateArgs = true;
ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+ }
}
- if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end());
- if (FunctionTemplate) Fns.push_back(FunctionTemplate);
-
// If we didn't actually find anything, we're done.
if (Fns.empty())
return 0;
@@ -5133,29 +5129,34 @@
SourceLocation RParenLoc) {
// Dig out the member expression. This holds both the object
// argument and the member function we're referring to.
- MemberExpr *MemExpr = 0;
- if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
- MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
- else
- MemExpr = dyn_cast<MemberExpr>(MemExprE);
- assert(MemExpr && "Building member call without member expression");
-
+ Expr *NakedMemExpr = MemExprE->IgnoreParens();
+
// Extract the object argument.
- Expr *ObjectArg = MemExpr->getBase();
+ Expr *ObjectArg;
+ MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
- if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
- isa<FunctionTemplateDecl>(MemExpr->getMemberDecl())) {
+ if (isa<MemberExpr>(NakedMemExpr)) {
+ MemExpr = cast<MemberExpr>(NakedMemExpr);
+ ObjectArg = MemExpr->getBase();
+ Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+ } else {
+ UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
+ ObjectArg = UnresExpr->getBase();
+
// Add overload candidates
OverloadCandidateSet CandidateSet;
- DeclarationName DeclName = MemExpr->getMemberDecl()->getDeclName();
- for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
- Func != FuncEnd; ++Func) {
- if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
+ for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
+ E = UnresExpr->decls_end(); I != E; ++I) {
+
+ // TODO: note if we found something through a using declaration
+ NamedDecl *Func = (*I)->getUnderlyingDecl();
+
+ if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
- if (MemExpr->hasExplicitTemplateArgumentList())
+ if (UnresExpr->hasExplicitTemplateArgs())
continue;
AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
@@ -5163,11 +5164,11 @@
} else {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgs;
- if (MemExpr->hasExplicitTemplateArgumentList())
- MemExpr->copyTemplateArgumentsInto(TemplateArgs);
+ if (UnresExpr->hasExplicitTemplateArgs())
+ UnresExpr->copyTemplateArgumentsInto(TemplateArgs);
- AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
- (MemExpr->hasExplicitTemplateArgumentList()
+ AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
+ (UnresExpr->hasExplicitTemplateArgs()
? &TemplateArgs : 0),
ObjectArg, Args, NumArgs,
CandidateSet,
@@ -5175,14 +5176,16 @@
}
}
+ DeclarationName DeclName = UnresExpr->getMemberName();
+
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) {
+ switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
break;
case OR_No_Viable_Function:
- Diag(MemExpr->getSourceRange().getBegin(),
+ Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@@ -5190,16 +5193,14 @@
return true;
case OR_Ambiguous:
- Diag(MemExpr->getSourceRange().getBegin(),
- diag::err_ovl_ambiguous_member_call)
+ Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
// FIXME: Leaking incoming expressions!
return true;
case OR_Deleted:
- Diag(MemExpr->getSourceRange().getBegin(),
- diag::err_ovl_deleted_member_call)
+ Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@@ -5208,13 +5209,7 @@
}
MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
- if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
- MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
- else
- MemExpr = dyn_cast<MemberExpr>(MemExprE);
-
- } else {
- Method = dyn_cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+ MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
assert(Method && "Member call to something that isn't a method?");
@@ -5660,15 +5655,10 @@
Fn->getType());
}
-
- if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
- assert((isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
- isa<FunctionTemplateDecl>(MemExpr->getMemberDecl()) ||
- isa<FunctionDecl>(MemExpr->getMemberDecl())) &&
- "Expected member function or member function template");
+ if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgs;
- if (MemExpr->hasExplicitTemplateArgumentList())
+ if (MemExpr->hasExplicitTemplateArgs())
MemExpr->copyTemplateArgumentsInto(TemplateArgs);
return MemberExpr::Create(Context, MemExpr->getBase()->Retain(),
@@ -5677,7 +5667,7 @@
MemExpr->getQualifierRange(),
Fn,
MemExpr->getMemberLoc(),
- (MemExpr->hasExplicitTemplateArgumentList()
+ (MemExpr->hasExplicitTemplateArgs()
? &TemplateArgs : 0),
Fn->getType());
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Nov 30 16:42:35 2009
@@ -867,13 +867,10 @@
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType));
- return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
- OperatorLoc,
- isArrow? tok::arrow : tok::period,
- DestroyedTypeLoc,
- Name,
- Sema::DeclPtrTy::make((Decl *)0),
- &SS);
+ return getSema().BuildMemberReferenceExpr(move(Base), OperatorLoc, isArrow,
+ SS, /*FIXME: FirstQualifier*/ 0,
+ Name, DestroyedTypeLoc,
+ /*TemplateArgs*/ 0);
}
/// \brief Build a new unary operator expression.
@@ -967,14 +964,10 @@
SS.setScopeRep(Qualifier);
}
- return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
- isArrow? tok::arrow : tok::period,
- MemberLoc,
- Member->getDeclName(),
- ExplicitTemplateArgs,
- /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
- &SS,
- FirstQualifierInScope);
+ return getSema().BuildMemberReferenceExpr(move(Base), OpLoc, isArrow,
+ SS, FirstQualifierInScope,
+ Member->getDeclName(), MemberLoc,
+ ExplicitTemplateArgs);
}
/// \brief Build a new binary operator expression.
@@ -1049,10 +1042,13 @@
SourceLocation OpLoc,
SourceLocation AccessorLoc,
IdentifierInfo &Accessor) {
- return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
- tok::period, AccessorLoc,
+ CXXScopeSpec SS;
+ return getSema().BuildMemberReferenceExpr(move(Base),
+ OpLoc, /*IsArrow*/ false,
+ SS, /*FirstQualifierInScope*/ 0,
DeclarationName(&Accessor),
- /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+ AccessorLoc,
+ /* TemplateArgs */ 0);
}
/// \brief Build a new initializer list expression.
@@ -1530,67 +1526,38 @@
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
+ NamedDecl *FirstQualifierInScope,
DeclarationName Name,
SourceLocation MemberLoc,
- NamedDecl *FirstQualifierInScope) {
- OwningExprResult Base = move(BaseE);
- tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
-
+ const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
- return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0,
- move(Base), OperatorLoc, OpKind,
- MemberLoc,
- Name,
- /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
- &SS,
- FirstQualifierInScope);
+ return SemaRef.BuildMemberReferenceExpr(move(BaseE), OperatorLoc, IsArrow,
+ SS, FirstQualifierInScope,
+ Name, MemberLoc, TemplateArgs);
}
- /// \brief Build a new member reference expression with explicit template
- /// arguments.
+ /// \brief Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- TemplateName Template,
- SourceLocation TemplateNameLoc,
- NamedDecl *FirstQualifierInScope,
- const TemplateArgumentListInfo &TemplateArgs) {
+ OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE,
+ SourceLocation OperatorLoc,
+ bool IsArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
OwningExprResult Base = move(BaseE);
- tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
- // FIXME: We're going to end up looking up the template based on its name,
- // twice! Also, duplicates part of Sema::BuildMemberAccessExpr.
- DeclarationName Name;
- if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
- Name = ActualTemplate->getDeclName();
- else if (OverloadedFunctionDecl *Ovl
- = Template.getAsOverloadedFunctionDecl())
- Name = Ovl->getDeclName();
- else {
- DependentTemplateName *DTN = Template.getAsDependentTemplateName();
- if (DTN->isIdentifier())
- Name = DTN->getIdentifier();
- else
- Name = SemaRef.Context.DeclarationNames.getCXXOperatorName(
- DTN->getOperator());
- }
- return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
- OperatorLoc, OpKind,
- TemplateNameLoc, Name,
- &TemplateArgs,
- Sema::DeclPtrTy(), &SS);
+ return SemaRef.BuildMemberReferenceExpr(move(Base), OperatorLoc, IsArrow,
+ SS, R, TemplateArgs);
}
/// \brief Build a new Objective-C @encode expression.
@@ -4903,28 +4870,12 @@
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
+ FirstQualifierInScope,
Name,
E->getMemberLoc(),
- FirstQualifierInScope);
+ /*TemplateArgs*/ 0);
}
- // FIXME: This is an ugly hack, which forces the same template name to
- // be looked up multiple times. Yuck!
- TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName());
- TemplateName OrigTemplateName;
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
- OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II);
- else
- OrigTemplateName
- = SemaRef.Context.getDependentTemplateName(0,
- Name.getCXXOverloadedOperator());
-
- TemplateName Template
- = getDerived().TransformTemplateName(OrigTemplateName,
- QualType::getFromOpaquePtr(ObjectType));
- if (Template.isNull())
- return SemaRef.ExprError();
-
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
@@ -4938,10 +4889,75 @@
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
- Template,
- E->getMemberLoc(),
FirstQualifierInScope,
- TransArgs);
+ Name,
+ E->getMemberLoc(),
+ &TransArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old,
+ bool isAddressOfOperand) {
+ // Transform the base of the expression.
+ OwningExprResult Base = getDerived().TransformExpr(Old->getBase());
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ NestedNameSpecifier *Qualifier = 0;
+ if (Old->getQualifier()) {
+ Qualifier
+ = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+ Old->getQualifierRange());
+ if (Qualifier == 0)
+ return SemaRef.ExprError();
+ }
+
+ LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
+ Sema::LookupOrdinaryName);
+
+ // Transform all the decls.
+ for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
+ E = Old->decls_end(); I != E; ++I) {
+ NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
+ if (!InstD)
+ return SemaRef.ExprError();
+
+ // Expand using declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+ for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+ E = UD->shadow_end(); I != E; ++I)
+ R.addDecl(*I);
+ continue;
+ }
+
+ R.addDecl(InstD);
+ }
+
+ R.resolveKind();
+
+ TemplateArgumentListInfo TransArgs;
+ if (Old->hasExplicitTemplateArgs()) {
+ TransArgs.setLAngleLoc(Old->getLAngleLoc());
+ TransArgs.setRAngleLoc(Old->getRAngleLoc());
+ for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
+ TemplateArgumentLoc Loc;
+ if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I],
+ Loc))
+ return SemaRef.ExprError();
+ TransArgs.addArgument(Loc);
+ }
+ }
+
+ return getDerived().RebuildUnresolvedMemberExpr(move(Base),
+ Old->getOperatorLoc(),
+ Old->isArrow(),
+ Qualifier,
+ Old->getQualifierRange(),
+ R,
+ (Old->hasExplicitTemplateArgs()
+ ? &TransArgs : 0));
}
template<typename Derived>
Modified: cfe/trunk/test/SemaCXX/qual-id-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qual-id-test.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/qual-id-test.cpp (original)
+++ cfe/trunk/test/SemaCXX/qual-id-test.cpp Mon Nov 30 16:42:35 2009
@@ -48,7 +48,7 @@
a.A::sub::x();
a.A::B::base::x();
- a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
+ a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
a->foo();
a->member::foo();
@@ -69,7 +69,7 @@
a->A::sub::x();
a->A::B::base::x();
- a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
+ a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
(*a)->foo();
(*a)->member::foo();
Modified: cfe/trunk/test/SemaTemplate/instantiate-method.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-method.cpp?rev=90161&r1=90160&r2=90161&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-method.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-method.cpp Mon Nov 30 16:42:35 2009
@@ -95,7 +95,9 @@
template<typename U>
struct X1 : X0<U> {
int &f2() {
- return X0Base::f(); // expected-error{{call to non-static member function without an object argument}}
+ // FIXME: We should be able to do this lookup and diagnose the error
+ // *despite* the fact that we can't decide the relationship yet.
+ return X0Base::f(); // expected-FIXME-error{{call to non-static member function without an object argument}}
}
};
More information about the cfe-commits
mailing list