aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-30 22:42:35 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-30 22:42:35 +0000
commit129e2df52ed7e0434b3f1cf1867fd6a5cb083ff6 (patch)
tree06f74638a1c208fe9589dccbb0c0c59e48f3d0fb
parentabce6999b271f4928aa98b11d42ffebedcde1e13 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90161 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h2
-rw-r--r--include/clang/AST/ExprCXX.h173
-rw-r--r--include/clang/AST/Stmt.h8
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/AST/Expr.cpp1
-rw-r--r--lib/AST/ExprCXX.cpp49
-rw-r--r--lib/AST/StmtPrinter.cpp18
-rw-r--r--lib/AST/StmtProfile.cpp13
-rw-r--r--lib/Sema/Lookup.h4
-rw-r--r--lib/Sema/Sema.h70
-rw-r--r--lib/Sema/SemaDecl.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp920
-rw-r--r--lib/Sema/SemaExprCXX.cpp40
-rw-r--r--lib/Sema/SemaOverload.cpp92
-rw-r--r--lib/Sema/TreeTransform.h182
-rw-r--r--test/SemaCXX/qual-id-test.cpp4
-rw-r--r--test/SemaTemplate/instantiate-method.cpp4
18 files changed, 1044 insertions, 541 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 6c50c7b48d..f7944771ef 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -73,6 +73,8 @@ public:
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(); }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index ce29d84c5c..23844ce5d9 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1617,6 +1617,179 @@ public:
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
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index cd5cfd4d37..d6f6a834d9 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -171,6 +171,14 @@ public:
}
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);
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 316521b4e4..7102336180 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -133,6 +133,7 @@ EXPR(CXXExprWithTemporaries , Expr)
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
EXPR(CXXUnresolvedConstructExpr, Expr)
EXPR(CXXDependentScopeMemberExpr, Expr)
+EXPR(UnresolvedMemberExpr , Expr)
// Obj-C Expressions.
EXPR(ObjCStringLiteral , Expr)
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c55d0bef3f..a0e03fed16 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2085,6 +2085,8 @@ def err_base_init_direct_and_virtual : Error<
"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">;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e4de703029..624a620b9f 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1525,6 +1525,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
case Expr::CXXDependentScopeMemberExprClass:
+ case Expr::UnresolvedMemberExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCMessageExprClass:
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 0e724a8d5c..d1a0390a0a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -573,3 +573,52 @@ Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() {
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);
+}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 2ea9748cbb..205ea0d182 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1163,6 +1163,24 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
}
}
+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");
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 914208b71e..d832a4649e 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -558,6 +558,19 @@ StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
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) {
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index c7b574fd66..e2134a2683 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -213,6 +213,10 @@ public:
return getResultKind() == FoundOverloaded;
}
+ bool isUnresolvableResult() const {
+ return getResultKind() == FoundUnresolvedValue;
+ }
+
LookupResultKind getResultKind() const {
sanity();
return ResultKind;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 232b502bf9..b594eceaf3 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -459,13 +459,20 @@ public:
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 @@ public:
/// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
DeclarationName GetNameForDeclarator(Declarator &D);
- DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
+ 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 @@ public:
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(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);
- OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+ 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 @@ public:
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
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 220ceddbf6..c987a7f11c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1757,7 +1757,7 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
}
/// \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);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 8def7d4efc..94449e2770 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -617,7 +617,54 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
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 @@ static void DecomposeTemplateName(LookupResult &R, TemplateName TName) {
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 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
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 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// 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 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// 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 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
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 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) {
/// \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 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS,
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,
-