[cfe-commits] r89544 - in /cfe/trunk: include/clang/AST/ lib/AST/ lib/Sema/ test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/ test/SemaObjC/
John McCall
rjmccall at apple.com
Sat Nov 21 00:51:08 PST 2009
Author: rjmccall
Date: Sat Nov 21 02:51:07 2009
New Revision: 89544
URL: http://llvm.org/viewvc/llvm-project?rev=89544&view=rev
Log:
"Incremental" progress on using expressions, by which I mean totally ripping
into pretty much everything about overload resolution in order to wean
BuildDeclarationNameExpr off LookupResult::getAsSingleDecl(). Replace
UnresolvedFunctionNameExpr with UnresolvedLookupExpr, which generalizes the
idea of a non-member lookup that we haven't totally resolved yet, whether by
overloading, argument-dependent lookup, or (eventually) the presence of
a function template in the lookup results.
Incidentally fixes a problem with argument-dependent lookup where we were
still performing ADL even when the lookup results contained something from
a block scope.
Incidentally improves a diagnostic when using an ObjC ivar from a class method.
This just fell out from rewriting BuildDeclarationNameExpr's interaction with
lookup, and I'm too apathetic to break it out.
The only remaining uses of OverloadedFunctionDecl that I know of are in
TemplateName and MemberExpr.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/StmtNodes.def
cfe/trunk/lib/AST/DeclCXX.cpp
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/SemaCodeComplete.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sat Nov 21 02:51:07 2009
@@ -88,6 +88,28 @@
namespace clang {
+/// UnresolvedSet - A set of unresolved declarations.
+class UnresolvedSet {
+ typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
+ DeclsTy Decls;
+
+public:
+ void addDecl(NamedDecl *D) {
+ Decls.push_back(D);
+ }
+
+ bool replace(const NamedDecl* Old, NamedDecl *New) {
+ for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I)
+ if (*I == Old)
+ return (*I = New, true);
+ return false;
+ }
+
+ typedef DeclsTy::const_iterator iterator;
+ iterator begin() const { return Decls.begin(); }
+ iterator end() const { return Decls.end(); }
+};
+
/// OverloadedFunctionDecl - An instance of this class represents a
/// set of overloaded functions. All of the functions have the same
/// name and occur within the same scope.
@@ -376,13 +398,13 @@
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
/// CXXConversionDecl.
- OverloadedFunctionDecl Conversions;
+ UnresolvedSet Conversions;
/// VisibleConversions - Overload set containing the conversion functions
/// of this C++ class and all those inherited conversion functions that
/// are visible in this class. Each of the entries in this overload set is
/// a CXXConversionDecl or a FunctionTemplateDecl.
- OverloadedFunctionDecl VisibleConversions;
+ UnresolvedSet VisibleConversions;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@@ -400,7 +422,7 @@
const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet,
const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes);
void collectConversionFunctions(
- llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet);
+ llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const;
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -581,22 +603,34 @@
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
- OverloadedFunctionDecl *getConversionFunctions() {
+ UnresolvedSet *getConversionFunctions() {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
- const OverloadedFunctionDecl *getConversionFunctions() const {
+ const UnresolvedSet *getConversionFunctions() const {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
+ typedef UnresolvedSet::iterator conversion_iterator;
+ conversion_iterator conversion_begin() const { return Conversions.begin(); }
+ conversion_iterator conversion_end() const { return Conversions.end(); }
+
+ /// Replaces a conversion function with a new declaration.
+ ///
+ /// Returns true if the old conversion was found.
+ bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
+ return Conversions.replace(Old, New);
+ }
+
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
- OverloadedFunctionDecl *getVisibleConversionFunctions();
+ const UnresolvedSet *getVisibleConversionFunctions();
+
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Sat Nov 21 02:51:07 2009
@@ -17,6 +17,7 @@
#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
namespace clang {
@@ -975,52 +976,6 @@
virtual child_iterator child_end();
};
-/// \brief Represents the name of a function that has not been
-/// resolved to any declaration.
-///
-/// Unresolved function names occur when a function name is
-/// encountered prior to an open parentheses ('(') in a C++ function
-/// call, and the function name itself did not resolve to a
-/// declaration. These function names can only be resolved when they
-/// form the postfix-expression of a function call, so that
-/// argument-dependent lookup finds declarations corresponding to
-/// these functions.
-
-/// @code
-/// template<typename T> void f(T x) {
-/// g(x); // g is an unresolved function name (that is also a dependent name)
-/// }
-/// @endcode
-class UnresolvedFunctionNameExpr : public Expr {
- /// The name that was present in the source
- DeclarationName Name;
-
- /// The location of this name in the source code
- SourceLocation Loc;
-
-public:
- UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L)
- : Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { }
-
- /// \brief Retrieves the name that occurred in the source code.
- DeclarationName getName() const { return Name; }
-
- /// getLocation - Retrieves the location in the source code where
- /// the name occurred.
- SourceLocation getLocation() const { return Loc; }
-
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == UnresolvedFunctionNameExprClass;
- }
- static bool classof(const UnresolvedFunctionNameExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
-
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
/// implementation of TR1/C++0x type trait templates.
/// Example:
@@ -1063,10 +1018,101 @@
virtual child_iterator child_end();
};
+/// \brief A reference to a name which we were able to look up during
+/// parsing but could not resolve to a specific declaration. This
+/// arises in several ways:
+/// * we might be waiting for argument-dependent lookup
+/// * the name might resolve to an overloaded function
+/// and eventually:
+/// * the lookup might have included a function template
+/// These never include UnresolvedUsingValueDecls, which are always
+/// class members and therefore appear only in
+/// UnresolvedMemberLookupExprs.
+class UnresolvedLookupExpr : public Expr {
+ /// The results. These are undesugared, which is to say, they may
+ /// include UsingShadowDecls.
+ UnresolvedSet Results;
+
+ /// The name declared.
+ DeclarationName Name;
+
+ /// The qualifier given, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// The source range of the nested name specifier.
+ SourceRange QualifierRange;
+
+ /// The location of the name.
+ SourceLocation NameLoc;
+
+ /// True if these lookup results should be extended by
+ /// argument-dependent lookup if this is the operand of a function
+ /// call.
+ bool RequiresADL;
+
+ UnresolvedLookupExpr(QualType T,
+ NestedNameSpecifier *Qualifier, SourceRange QRange,
+ DeclarationName Name, SourceLocation NameLoc,
+ bool RequiresADL)
+ : Expr(UnresolvedLookupExprClass, T, false, false),
+ Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
+ NameLoc(NameLoc), RequiresADL(RequiresADL)
+ {}
+
+public:
+ static UnresolvedLookupExpr *Create(ASTContext &C,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ bool ADL) {
+ return new(C) UnresolvedLookupExpr(C.OverloadTy, Qualifier, QualifierRange,
+ Name, NameLoc, ADL);
+ }
+
+ 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(); }
+
+ /// True if this declaration should be extended by
+ /// argument-dependent lookup.
+ bool requiresADL() const { return RequiresADL; }
+
+ /// Fetches the name looked up.
+ DeclarationName getName() const { return Name; }
+
+ /// Gets the location of the name.
+ SourceLocation getNameLoc() const { return NameLoc; }
+
+ /// Fetches the nested-name qualifier, if one was given.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// Fetches the range of the nested-name qualifier.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+
+ virtual SourceRange getSourceRange() const {
+ if (Qualifier) return SourceRange(QualifierRange.getBegin(), NameLoc);
+ return SourceRange(NameLoc, NameLoc);
+ }
+
+ virtual StmtIterator child_begin();
+ virtual StmtIterator child_end();
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedLookupExprClass;
+ }
+ static bool classof(const UnresolvedLookupExpr *) { return true; }
+};
+
/// \brief A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
-/// DependentScopeDeclRefExpr is similar to eclRefExpr in that
+/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// DependentScopeDeclRefExpr node is used only within C++ templates when
@@ -1377,9 +1423,9 @@
virtual child_iterator child_end();
};
-/// \brief Represents a C++ member access expression where the actual member
-/// referenced could not be resolved, e.g., because the base expression or the
-/// member name was dependent.
+/// \brief Represents a C++ member access expression where the actual
+/// member referenced could not be resolved because the base
+/// expression or the member name was dependent.
class CXXDependentScopeMemberExpr : public Expr {
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Sat Nov 21 02:51:07 2009
@@ -125,7 +125,7 @@
EXPR(CXXNewExpr , Expr)
EXPR(CXXDeleteExpr , Expr)
EXPR(CXXPseudoDestructorExpr, Expr)
-EXPR(UnresolvedFunctionNameExpr , Expr)
+EXPR(UnresolvedLookupExpr , Expr)
EXPR(UnaryTypeTraitExpr , Expr)
EXPR(DependentScopeDeclRefExpr , Expr)
EXPR(TemplateIdRefExpr , Expr)
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Nov 21 02:51:07 2009
@@ -36,8 +36,6 @@
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
- Conversions(DC, DeclarationName()),
- VisibleConversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -299,14 +297,11 @@
void
CXXRecordDecl::collectConversionFunctions(
- llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet)
+ llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const
{
- OverloadedFunctionDecl *TopConversions = getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- TFunc = TopConversions->function_begin(),
- TFuncEnd = TopConversions->function_end();
- TFunc != TFuncEnd; ++TFunc) {
- NamedDecl *TopConv = TFunc->get();
+ const UnresolvedSet *Cs = getConversionFunctions();
+ for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
+ NamedDecl *TopConv = *I;
CanQualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
dyn_cast<FunctionTemplateDecl>(TopConv))
@@ -336,14 +331,11 @@
bool inTopClass = (RD == this);
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
- OverloadedFunctionDecl *Conversions
+ const UnresolvedSet *Cs
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Func = Conversions->function_begin(),
- FuncEnd = Conversions->function_end();
- Func != FuncEnd; ++Func) {
- NamedDecl *Conv = Func->get();
+ for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
+ NamedDecl *Conv = *I;
// Only those conversions not exact match of conversions in current
// class are candidateconversion routines.
CanQualType ConvType;
@@ -405,8 +397,7 @@
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
-OverloadedFunctionDecl *
-CXXRecordDecl::getVisibleConversionFunctions() {
+const UnresolvedSet *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
return &Conversions;
@@ -425,26 +416,26 @@
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- VisibleConversions.addOverload(ConvDecl);
+ VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- VisibleConversions.addOverload(ConvDecl);
+ VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- Conversions.addOverload(ConvDecl);
+ Conversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- Conversions.addOverload(ConvDecl);
+ Conversions.addDecl(ConvDecl);
}
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sat Nov 21 02:51:07 2009
@@ -46,6 +46,7 @@
(HasExplicitTemplateArgumentList?
HasExplicitTemplateArgumentListFlag : 0)),
Loc(NameLoc) {
+ assert(!isa<OverloadedFunctionDecl>(D));
if (Qualifier) {
NameQualifier *NQ = getNameQualifier();
NQ->NNS = Qualifier;
@@ -1096,6 +1097,8 @@
return LV_Valid;
case PredefinedExprClass:
return LV_Valid;
+ case UnresolvedLookupExprClass:
+ return LV_Valid;
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
case CXXConditionDeclExprClass:
@@ -1500,7 +1503,7 @@
case Expr::CXXNewExprClass:
case Expr::CXXDeleteExprClass:
case Expr::CXXPseudoDestructorExprClass:
- case Expr::UnresolvedFunctionNameExprClass:
+ case Expr::UnresolvedLookupExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::TemplateIdRefExprClass:
case Expr::CXXConstructExprClass:
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Sat Nov 21 02:51:07 2009
@@ -121,11 +121,11 @@
return &Base + 1;
}
-// UnresolvedFunctionNameExpr
-Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() {
+// UnresolvedLookupExpr
+Stmt::child_iterator UnresolvedLookupExpr::child_begin() {
return child_iterator();
}
-Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() {
+Stmt::child_iterator UnresolvedLookupExpr::child_end() {
return child_iterator();
}
// UnaryTypeTraitExpr
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Sat Nov 21 02:51:07 2009
@@ -489,6 +489,10 @@
OS << Node->getDeclName().getAsString();
}
+void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
+ OS << Node->getName().getAsString();
+}
+
void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) {
if (Node->getQualifier())
Node->getQualifier()->print(OS, Policy);
@@ -1119,10 +1123,6 @@
OS << TypeS;
}
-void StmtPrinter::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *E) {
- OS << E->getName().getAsString();
-}
-
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
// Nothing to print.
}
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Sat Nov 21 02:51:07 2009
@@ -515,7 +515,7 @@
}
void
-StmtProfiler::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *S) {
+StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
VisitExpr(S);
VisitName(S->getName());
}
Modified: cfe/trunk/lib/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Lookup.h?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Sat Nov 21 02:51:07 2009
@@ -280,6 +280,12 @@
/// ambiguous and overloaded lookups.
NamedDecl *getAsSingleDecl(ASTContext &Context) const;
+ template <class DeclClass>
+ DeclClass *getAsSingle() const {
+ if (getResultKind() != Found) return 0;
+ return dyn_cast<DeclClass>(getFoundDecl());
+ }
+
/// \brief Fetch the unique decl found by this lookup. Asserts
/// that one was found.
///
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Nov 21 02:51:07 2009
@@ -959,7 +959,7 @@
bool Complain);
Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
- void AddOverloadedCallCandidates(NamedDecl *Callee,
+ void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees,
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
@@ -969,7 +969,8 @@
OverloadCandidateSet &CandidateSet,
bool PartialOverloading = false);
- FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
+ FunctionDecl *ResolveOverloadedCallFn(Expr *Fn,
+ llvm::SmallVectorImpl<NamedDecl*> &Fns,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
const TemplateArgumentLoc *ExplicitTemplateArgs,
@@ -1415,10 +1416,18 @@
bool HasTrailingLParen,
const CXXScopeSpec *SS,
bool isAddressOfOperand = false);
- OwningExprResult BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
+ OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ LookupResult &R, bool ADL,
bool isAddressOfOperand);
+ OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ SourceLocation Loc,
+ DeclarationName Name,
+ bool NeedsADL,
+ NamedDecl * const *Decls,
+ unsigned NumDecls);
+ OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ SourceLocation Loc,
+ NamedDecl *D);
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind);
@@ -1517,7 +1526,7 @@
SourceLocation RParenLoc);
void DeconstructCallFunction(Expr *FnExpr,
- NamedDecl *&Function,
+ llvm::SmallVectorImpl<NamedDecl*>& Fns,
DeclarationName &Name,
NestedNameSpecifier *&Qualifier,
SourceRange &QualifierRange,
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Sat Nov 21 02:51:07 2009
@@ -1467,7 +1467,7 @@
Expr::hasAnyTypeDependentArguments(Args, NumArgs))
return;
- NamedDecl *Function;
+ llvm::SmallVector<NamedDecl*,8> Fns;
DeclarationName UnqualifiedName;
NestedNameSpecifier *Qualifier;
SourceRange QualifierRange;
@@ -1476,8 +1476,7 @@
const TemplateArgumentLoc *ExplicitTemplateArgs;
unsigned NumExplicitTemplateArgs;
- DeconstructCallFunction(Fn,
- Function, UnqualifiedName, Qualifier, QualifierRange,
+ DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange,
ArgumentDependentLookup, HasExplicitTemplateArgs,
ExplicitTemplateArgs, NumExplicitTemplateArgs);
@@ -1488,7 +1487,7 @@
// Build an overload candidate set based on the functions we find.
OverloadCandidateSet CandidateSet;
- AddOverloadedCallCandidates(Function, UnqualifiedName,
+ AddOverloadedCallCandidates(Fns, UnqualifiedName,
ArgumentDependentLookup, HasExplicitTemplateArgs,
ExplicitTemplateArgs, NumExplicitTemplateArgs,
Args, NumArgs,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Nov 21 02:51:07 2009
@@ -2601,16 +2601,8 @@
if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
ExpectedPrevDecl = ConversionTemplate->getPreviousDeclaration();
- OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Conv = Conversions->function_begin(),
- ConvEnd = Conversions->function_end();
- Conv != ConvEnd; ++Conv) {
- if (*Conv == ExpectedPrevDecl) {
- *Conv = Conversion;
- return DeclPtrTy::make(Conversion);
- }
- }
+ if (ClassDecl->replaceConversion(ExpectedPrevDecl, Conversion))
+ return DeclPtrTy::make(Conversion);
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
} else if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
@@ -3895,18 +3887,17 @@
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet;
- OverloadedFunctionDecl *Conversions
+ const UnresolvedSet *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator Func
- = Conversions->function_begin();
- Func != Conversions->function_end(); ++Func) {
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
FunctionTemplateDecl *ConvTemplate
- = dyn_cast<FunctionTemplateDecl>(*Func);
+ = dyn_cast<FunctionTemplateDecl>(*I);
CXXConversionDecl *Conv;
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
- Conv = cast<CXXConversionDecl>(*Func);
+ Conv = cast<CXXConversionDecl>(*I);
// If the conversion function doesn't return a reference type,
// it can't be considered for this conversion.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Nov 21 02:51:07 2009
@@ -417,6 +417,8 @@
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS) {
+ assert(!isa<OverloadedFunctionDecl>(D));
+
if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
Diag(Loc,
diag::err_auto_variable_cannot_appear_in_own_initializer)
@@ -688,8 +690,6 @@
if (Lookup.isAmbiguous())
return ExprError();
- NamedDecl *D = Lookup.getAsSingleDecl(Context);
-
// If this reference is in an Objective-C method, then ivar lookup happens as
// well.
IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -699,44 +699,58 @@
// found a decl, but that decl is outside the current instance method (i.e.
// a global variable). In these two cases, we do a lookup for an ivar with
// this name, if the lookup sucedes, we replace it our current decl.
- if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) {
+
+ // FIXME: we should change lookup to do this.
+
+ // If we're in a class method, we don't normally want to look for
+ // ivars. But if we don't find anything else, and there's an
+ // ivar, that's an error.
+ bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+
+ bool LookForIvars;
+ if (Lookup.empty())
+ LookForIvars = true;
+ else if (IsClassMethod)
+ LookForIvars = false;
+ else
+ LookForIvars = (Lookup.isSingleResult() &&
+ Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+
+ if (LookForIvars) {
ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
- // Check if referencing a field with __attribute__((deprecated)).
- if (DiagnoseUseOfDecl(IV, Loc))
- return ExprError();
+ // Diagnose using an ivar in a class method.
+ if (IsClassMethod)
+ return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+ << IV->getDeclName());
// If we're referencing an invalid decl, just return this as a silent
// error node. The error diagnostic was already emitted on the decl.
if (IV->isInvalidDecl())
return ExprError();
- bool IsClsMethod = getCurMethodDecl()->isClassMethod();
- // If a class method attemps to use a free standing ivar, this is
- // an error.
- if (IsClsMethod && D && !D->isDefinedOutsideFunctionOrMethod())
- return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
- << IV->getDeclName());
- // If a class method uses a global variable, even if an ivar with
- // same name exists, use the global.
- if (!IsClsMethod) {
- if (IV->getAccessControl() == ObjCIvarDecl::Private &&
- ClassDeclared != IFace)
- Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
- // FIXME: This should use a new expr for a direct reference, don't
- // turn this into Self->ivar, just return a BareIVarExpr or something.
- IdentifierInfo &II = Context.Idents.get("self");
- UnqualifiedId SelfName;
- SelfName.setIdentifier(&II, SourceLocation());
- CXXScopeSpec SelfScopeSpec;
- OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
- SelfName, false, false);
- MarkDeclarationReferenced(Loc, IV);
- return Owned(new (Context)
- ObjCIvarRefExpr(IV, IV->getType(), Loc,
- SelfExpr.takeAs<Expr>(), true, true));
- }
+ // Check if referencing a field with __attribute__((deprecated)).
+ if (DiagnoseUseOfDecl(IV, Loc))
+ return ExprError();
+
+ // Diagnose the use of an ivar outside of the declaring class.
+ if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+ ClassDeclared != IFace)
+ Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+ // FIXME: This should use a new expr for a direct reference, don't
+ // turn this into Self->ivar, just return a BareIVarExpr or something.
+ IdentifierInfo &II = Context.Idents.get("self");
+ UnqualifiedId SelfName;
+ SelfName.setIdentifier(&II, SourceLocation());
+ CXXScopeSpec SelfScopeSpec;
+ OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ SelfName, false, false);
+ MarkDeclarationReferenced(Loc, IV);
+ return Owned(new (Context)
+ ObjCIvarRefExpr(IV, IV->getType(), Loc,
+ SelfExpr.takeAs<Expr>(), true, true));
}
} else if (getCurMethodDecl()->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
@@ -749,7 +763,7 @@
}
}
// Needed to implement property "super.method" notation.
- if (D == 0 && II->isStr("super")) {
+ if (Lookup.empty() && II->isStr("super")) {
QualType T;
if (getCurMethodDecl()->isInstanceMethod())
@@ -766,26 +780,14 @@
bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) &&
HasTrailingLParen;
- if (ADL && D == 0) {
- // We've seen something of the form
- //
- // identifier(
- //
- // and we did not find any entity by the name
- // "identifier". However, this identifier is still subject to
- // argument-dependent lookup, so keep track of the name.
- return Owned(new (Context) UnresolvedFunctionNameExpr(Name,
- Context.OverloadTy,
- Loc));
- }
-
- if (D == 0) {
+ if (Lookup.empty() && !ADL) {
// Otherwise, this could be an implicitly declared function reference (legal
// in C90, extension in C99).
if (HasTrailingLParen && II &&
- !getLangOptions().CPlusPlus) // Not in C++.
- D = ImplicitlyDefineFunction(Loc, *II, S);
- else {
+ !getLangOptions().CPlusPlus) { // Not in C++.
+ NamedDecl *D = ImplicitlyDefineFunction(Loc, *II, S);
+ if (D) Lookup.addDecl(D);
+ } else {
// If this name wasn't predeclared and if this is not a function call,
// diagnose the problem.
if (SS && !SS->isEmpty())
@@ -801,7 +803,7 @@
}
}
- if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (VarDecl *Var = Lookup.getAsSingle<VarDecl>()) {
// Warn about constructs like:
// if (void *X = foo()) { ... } else { X }.
// In the else block, the pointer is always false.
@@ -824,7 +826,7 @@
CheckS = CheckS->getParent();
}
}
- } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
+ } else if (FunctionDecl *Func = Lookup.getAsSingle<FunctionDecl>()) {
if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
// C99 DR 316 says that, if a function type comes from a
// function definition (without a prototype), that type is only
@@ -842,8 +844,10 @@
}
}
- return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand);
+ return BuildDeclarationNameExpr(SS, Lookup, HasTrailingLParen,
+ isAddressOfOperand);
}
+
/// \brief Cast member's object to its own class if necessary.
bool
Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) {
@@ -887,53 +891,28 @@
return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
}
-/// \brief Complete semantic analysis for a reference to the given declaration.
-Sema::OwningExprResult
-Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand) {
- assert(D && "Cannot refer to a NULL declaration");
- DeclarationName Name = D->getDeclName();
-
- // If this is an expression of the form &Class::member, don't build an
- // implicit member ref, because we want a pointer to the member in general,
- // not any specific instance's member.
- if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) {
- DeclContext *DC = computeDeclContext(*SS);
- if (D && isa<CXXRecordDecl>(DC)) {
- QualType DType;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- DType = FD->getType().getNonReferenceType();
- } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- DType = Method->getType();
- } else if (isa<OverloadedFunctionDecl>(D)) {
- DType = Context.OverloadTy;
- }
- // Could be an inner type. That's diagnosed below, so ignore it here.
- if (!DType.isNull()) {
- // The pointer is type- and value-dependent if it points into something
- // dependent.
- bool Dependent = DC->isDependentContext();
- return BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS);
- }
- }
- }
+/// Builds an implicit member access expression from the given
+/// unqualified lookup set, which is known to contain only class
+/// members.
+Sema::OwningExprResult BuildImplicitMemberExpr(Sema &S, LookupResult &R,
+ const CXXScopeSpec *SS) {
+ NamedDecl *D = R.getAsSingleDecl(S.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?
if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
- return BuildAnonymousStructUnionMemberReference(Loc, FD);
+ return S.BuildAnonymousStructUnionMemberReference(Loc, FD);
- // Cope with an implicit member access in a C++ non-static member function.
- QualType ThisType, MemberType;
- if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) {
- Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
- MarkDeclarationReferenced(Loc, D);
- if (PerformObjectMemberConversion(This, D))
- return ExprError();
+ QualType ThisType;
+ QualType MemberType;
+ if (S.isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) {
+ Expr *This = new (S.Context) CXXThisExpr(SourceLocation(), ThisType);
+ S.MarkDeclarationReferenced(Loc, D);
+ if (S.PerformObjectMemberConversion(This, D))
+ return S.ExprError();
bool ShouldCheckUse = true;
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
@@ -943,45 +922,196 @@
ShouldCheckUse = false;
}
- if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
- return ExprError();
- return Owned(BuildMemberExpr(Context, This, true, SS, D,
- Loc, MemberType));
+ if (ShouldCheckUse && S.DiagnoseUseOfDecl(D, Loc))
+ return S.ExprError();
+ return S.Owned(BuildMemberExpr(S.Context, This, true, SS, D,
+ Loc, MemberType));
}
- if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
- if (MD->isStatic())
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (!Method->isStatic()) {
+ S.Diag(Loc, diag::err_member_call_without_object);
+ return S.ExprError();
+ }
+ }
+
+ if (isa<FieldDecl>(D)) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S.CurContext)) {
+ if (MD->isStatic()) {
// "invalid use of member 'x' in static member function"
- return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
- << FD->getDeclName());
+ S.Diag(Loc,diag::err_invalid_member_use_in_static_method)
+ << D->getDeclName();
+ return S.ExprError();
+ }
}
// Any other ways we could have found the field in a well-formed
// program would have been turned into implicit member expressions
// above.
- return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use)
- << FD->getDeclName());
+ S.Diag(Loc, diag::err_invalid_non_static_member_use)
+ << D->getDeclName();
+ return S.ExprError();
+ }
+
+ return S.BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getLookupName(),
+ /*ADL*/ false,
+ R.begin(), R.end() - R.begin());
+}
+
+static bool UseArgumentDependentLookup(Sema &SemaRef,
+ const CXXScopeSpec *SS,
+ bool HasTrailingLParen,
+ const LookupResult &R) {
+ // Only when used directly as the postfix-expression of a call.
+ if (!HasTrailingLParen)
+ return false;
+
+ // Never if a scope specifier was provided.
+ if (SS && SS->isSet())
+ return false;
+
+ // Only in C++ or ObjC++.
+ if (!SemaRef.getLangOptions().CPlusPlus)
+ return false;
+
+ // Turn off ADL when we find certain kinds of declarations during
+ // normal lookup:
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ NamedDecl *D = *I;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a declaration of a class member
+ // Since using decls preserve this property, we check this on the
+ // original decl.
+ if (D->getDeclContext()->isRecord())
+ return false;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a block-scope function declaration that is not a
+ // using-declaration
+ // NOTE: we also trigger this for function templates (in fact, we
+ // don't check the decl type at all, since all other decl types
+ // turn off ADL anyway).
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ else if (D->getDeclContext()->isFunctionOrMethod())
+ return false;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a declaration that is neither a function or a function
+ // template
+ // And also for builtin functions.
+ if (isa<FunctionDecl>(D)) {
+ FunctionDecl *FDecl = cast<FunctionDecl>(D);
+
+ // But also builtin functions.
+ if (FDecl->getBuiltinID() && FDecl->isImplicit())
+ return false;
+ } else if (!isa<FunctionTemplateDecl>(D))
+ return false;
+ }
+
+ return true;
+}
+
+
+/// \brief Complete semantic analysis for a reference to the given
+/// lookup results.
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ LookupResult &R,
+ bool HasTrailingLParen,
+ bool isAddressOfOperand) {
+ assert(!R.isAmbiguous() && "results are ambiguous");
+
+ // &SomeClass::foo is an abstract member reference, regardless of
+ // the nature of foo, but &SomeClass::foo(...) is not.
+ bool isAbstractMemberPointer =
+ (isAddressOfOperand && !HasTrailingLParen && SS && !SS->isEmpty());
+
+ // If we're *not* an abstract member reference, and any of the
+ // results are class members (i.e. they're all class members), then
+ // we make an implicit member reference instead.
+ if (!isAbstractMemberPointer && !R.empty() &&
+ isa<CXXRecordDecl>((*R.begin())->getDeclContext())) {
+ return BuildImplicitMemberExpr(*this, R, SS);
+ }
+
+ assert(R.getResultKind() != LookupResult::FoundUnresolvedValue &&
+ "found UnresolvedUsingValueDecl in non-class scope");
+
+ bool ADL = UseArgumentDependentLookup(*this, SS, HasTrailingLParen, R);
+
+ return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getLookupName(), ADL,
+ R.begin(), R.end() - R.begin());
+}
+
+/// Diagnoses obvious problems with the use of the given declaration
+/// as an expression. This is only actually called for lookups that
+/// were not overloaded, and it doesn't promise that the declaration
+/// will in fact be used.
+static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
+ if (isa<TypedefDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
+ return true;
+ }
+
+ if (isa<ObjCInterfaceDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName();
+ return true;
+ }
+
+ if (isa<NamespaceDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName();
+ return true;
}
- if (isa<TypedefDecl>(D))
- return ExprError(Diag(Loc, diag::err_unexpected_typedef) << Name);
- if (isa<ObjCInterfaceDecl>(D))
- return ExprError(Diag(Loc, diag::err_unexpected_interface) << Name);
- if (isa<NamespaceDecl>(D))
- return ExprError(Diag(Loc, diag::err_unexpected_namespace) << Name);
+ return false;
+}
+
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ SourceLocation Loc,
+ DeclarationName Name,
+ bool NeedsADL,
+ NamedDecl * const *Decls,
+ unsigned NumDecls) {
+ if (!NeedsADL && NumDecls == 1)
+ return BuildDeclarationNameExpr(SS, Loc, Decls[0]->getUnderlyingDecl());
+
+ // We only need to check the declaration if there's exactly one
+ // result, because in the overloaded case the results can only be
+ // functions and function templates.
+ if (NumDecls == 1 &&
+ CheckDeclInExpr(*this, Loc, Decls[0]->getUnderlyingDecl()))
+ return ExprError();
+
+ UnresolvedLookupExpr *ULE
+ = UnresolvedLookupExpr::Create(Context,
+ SS ? (NestedNameSpecifier *)SS->getScopeRep() : 0,
+ SS ? SS->getRange() : SourceRange(),
+ Name, Loc, NeedsADL);
+ for (unsigned I = 0; I != NumDecls; ++I)
+ ULE->addDecl(Decls[I]);
+
+ return Owned(ULE);
+}
+
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+ SourceLocation Loc, NamedDecl *D) {
+ assert(D && "Cannot refer to a NULL declaration");
+ DeclarationName Name = D->getDeclName();
+
+ if (CheckDeclInExpr(*this, Loc, D))
+ return ExprError();
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
- if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
- return BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc,
- false, false, SS);
- else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
false, false, SS);
- else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D))
- return BuildDeclRefExpr(UD, Context.DependentTy, Loc,
- /*TypeDependent=*/true,
- /*ValueDependent=*/true, SS);
ValueDecl *VD = cast<ValueDecl>(D);
@@ -989,9 +1119,7 @@
// this check when we're going to perform argument-dependent lookup
// on this function name, because this might not be the function
// that overload resolution actually selects.
- bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) &&
- HasTrailingLParen;
- if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc))
+ if (DiagnoseUseOfDecl(VD, Loc))
return ExprError();
// Only create DeclRefExpr's for valid Decl's.
@@ -1038,9 +1166,8 @@
TypeDependent = true;
// - a nested-name-specifier that contains a class-name that
// names a dependent type.
- else if (SS && !SS->isEmpty()) {
- for (DeclContext *DC = computeDeclContext(*SS);
- DC; DC = DC->getParent()) {
+ else {
+ for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) {
// FIXME: could stop early at namespace scope.
if (DC->isRecord()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
@@ -2557,7 +2684,7 @@
/// whether argument-dependent lookup is available, whether it has explicit
/// template arguments, etc.
void Sema::DeconstructCallFunction(Expr *FnExpr,
- NamedDecl *&Function,
+ llvm::SmallVectorImpl<NamedDecl*> &Fns,
DeclarationName &Name,
NestedNameSpecifier *&Qualifier,
SourceRange &QualifierRange,
@@ -2566,7 +2693,6 @@
const TemplateArgumentLoc *&ExplicitTemplateArgs,
unsigned &NumExplicitTemplateArgs) {
// Set defaults for all of the output parameters.
- Function = 0;
Name = DeclarationName();
Qualifier = 0;
QualifierRange = SourceRange();
@@ -2589,21 +2715,29 @@
== UnaryOperator::AddrOf) {
FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
} else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
- Function = dyn_cast<NamedDecl>(DRExpr->getDecl());
- if ((Qualifier = DRExpr->getQualifier())) {
- ArgumentDependentLookup = false;
+ Fns.push_back(cast<NamedDecl>(DRExpr->getDecl()));
+ ArgumentDependentLookup = false;
+ if ((Qualifier = DRExpr->getQualifier()))
QualifierRange = DRExpr->getQualifierRange();
- }
break;
- } else if (UnresolvedFunctionNameExpr *DepName
- = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) {
- Name = DepName->getName();
+ } else if (UnresolvedLookupExpr *UnresLookup
+ = dyn_cast<UnresolvedLookupExpr>(FnExpr)) {
+ Name = UnresLookup->getName();
+ Fns.append(UnresLookup->decls_begin(), UnresLookup->decls_end());
+ ArgumentDependentLookup = UnresLookup->requiresADL();
+ if ((Qualifier = UnresLookup->getQualifier()))
+ QualifierRange = UnresLookup->getQualifierRange();
break;
} else if (TemplateIdRefExpr *TemplateIdRef
= dyn_cast<TemplateIdRefExpr>(FnExpr)) {
- Function = TemplateIdRef->getTemplateName().getAsTemplateDecl();
- if (!Function)
- Function = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl();
+ if (NamedDecl *Function
+ = TemplateIdRef->getTemplateName().getAsTemplateDecl())
+ Fns.push_back(Function);
+ else {
+ OverloadedFunctionDecl *Overload
+ = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl();
+ Fns.append(Overload->function_begin(), Overload->function_end());
+ }
HasExplicitTemplateArguments = true;
ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs();
NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs();
@@ -2653,9 +2787,6 @@
Expr *Fn = fn.takeAs<Expr>();
Expr **Args = reinterpret_cast<Expr**>(args.release());
assert(Fn && "no function call expression");
- FunctionDecl *FDecl = NULL;
- NamedDecl *NDecl = NULL;
- DeclarationName UnqualifiedName;
if (getLangOptions().CPlusPlus) {
// If this is a pseudo-destructor expression, build the call immediately.
@@ -2742,39 +2873,43 @@
// If we're directly calling a function, get the appropriate declaration.
// Also, in C++, keep track of whether we should perform argument-dependent
// lookup and whether there were any explicitly-specified template arguments.
+ llvm::SmallVector<NamedDecl*,8> Fns;
+ DeclarationName UnqualifiedName;
bool ADL = true;
bool HasExplicitTemplateArgs = 0;
const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
- DeconstructCallFunction(Fn, NDecl, UnqualifiedName, Qualifier, QualifierRange,
+ DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange,
ADL,HasExplicitTemplateArgs, ExplicitTemplateArgs,
NumExplicitTemplateArgs);
- OverloadedFunctionDecl *Ovl = 0;
+ NamedDecl *NDecl = 0; // the specific declaration we're calling, if applicable
+ FunctionDecl *FDecl = 0; // same, if it's a function or function template
FunctionTemplateDecl *FunctionTemplate = 0;
- if (NDecl) {
+
+ if (Fns.size() == 1) {
+ NDecl = Fns[0];
FDecl = dyn_cast<FunctionDecl>(NDecl);
if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(NDecl)))
FDecl = FunctionTemplate->getTemplatedDecl();
else
FDecl = dyn_cast<FunctionDecl>(NDecl);
- Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl);
}
- if (Ovl || FunctionTemplate ||
+ if (Fns.size() > 1 || FunctionTemplate ||
(getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
// We don't perform ADL for implicit declarations of builtins.
if (FDecl && FDecl->getBuiltinID() && FDecl->isImplicit())
- ADL = false;
+ assert(!ADL); // this should be guaranteed earlier
// We don't perform ADL in C.
if (!getLangOptions().CPlusPlus)
- ADL = false;
+ assert(!ADL); // ditto
- if (Ovl || FunctionTemplate || ADL) {
- FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName,
+ if (Fns.size() > 1 || FunctionTemplate || ADL) {
+ FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName,
HasExplicitTemplateArgs,
ExplicitTemplateArgs,
NumExplicitTemplateArgs,
@@ -2784,6 +2919,8 @@
return ExprError();
Fn = FixOverloadedFunctionReference(Fn, FDecl);
+
+ NDecl = FDecl;
}
}
@@ -5123,6 +5260,8 @@
// FIXME: Can LHS ever be null here?
if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull())
return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc);
+ } else if (isa<UnresolvedLookupExpr>(op)) {
+ return Context.OverloadTy;
} else if (dcl) { // C99 6.5.3.2p1
// We have an lvalue with a decl. Make sure the decl is not declared
// with the register storage-class specifier.
@@ -5132,8 +5271,7 @@
<< "register variable" << op->getSourceRange();
return QualType();
}
- } else if (isa<OverloadedFunctionDecl>(dcl) ||
- isa<FunctionTemplateDecl>(dcl)) {
+ } else if (isa<FunctionTemplateDecl>(dcl)) {
return Context.OverloadTy;
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) {
// Okay: we can take the address of a field.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Nov 21 02:51:07 2009
@@ -855,18 +855,15 @@
if (const RecordType *Record = Type->getAs<RecordType>()) {
llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- OverloadedFunctionDecl *Conversions =
- RD->getVisibleConversionFunctions();
+ const UnresolvedSet *Conversions = RD->getVisibleConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Func = Conversions->function_begin(),
- FuncEnd = Conversions->function_end();
- Func != FuncEnd; ++Func) {
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
// Skip over templated conversion functions; they aren't considered.
- if (isa<FunctionTemplateDecl>(*Func))
+ if (isa<FunctionTemplateDecl>(*I))
continue;
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
QualType ConvType = Conv->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
@@ -2310,6 +2307,9 @@
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);
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Sat Nov 21 02:51:07 2009
@@ -1525,33 +1525,29 @@
// in which the function or function template is defined and the
// classes and namespaces associated with its (non-dependent)
// parameter types and return type.
- DeclRefExpr *DRE = 0;
- TemplateIdRefExpr *TIRE = 0;
Arg = Arg->IgnoreParens();
- if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) {
- if (unaryOp->getOpcode() == UnaryOperator::AddrOf) {
- DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr());
- TIRE = dyn_cast<TemplateIdRefExpr>(unaryOp->getSubExpr());
- }
- } else {
- DRE = dyn_cast<DeclRefExpr>(Arg);
- TIRE = dyn_cast<TemplateIdRefExpr>(Arg);
- }
-
- OverloadedFunctionDecl *Ovl = 0;
- if (DRE)
- Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
- else if (TIRE)
- Ovl = TIRE->getTemplateName().getAsOverloadedFunctionDecl();
- if (!Ovl)
+ if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
+ if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
+ Arg = unaryOp->getSubExpr();
+
+ // TODO: avoid the copies. This should be easy when the cases
+ // share a storage implementation.
+ llvm::SmallVector<NamedDecl*, 8> Functions;
+
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
+ Functions.append(ULE->decls_begin(), ULE->decls_end());
+ else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(Arg)) {
+ TemplateName TName = TIRE->getTemplateName();
+ OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl();
+ Functions.append(Ovl->function_begin(), Ovl->function_end());
+ } else
continue;
- for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
- FuncEnd = Ovl->function_end();
- Func != FuncEnd; ++Func) {
- FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func);
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
+ E = Functions.end(); I != E; ++I) {
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I);
if (!FDecl)
- FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl();
+ FDecl = cast<FunctionTemplateDecl>(*I)->getTemplatedDecl();
// Add the namespace in which this function was defined. Note
// that, if this is a member function, we do *not* consider the
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Nov 21 02:51:07 2009
@@ -1353,18 +1353,6 @@
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
-/// \brief Given a function template or function, extract the function template
-/// declaration (if any) and the underlying function declaration.
-template<typename T>
-static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function,
- FunctionTemplateDecl *&FunctionTemplate) {
- FunctionTemplate = dyn_cast<FunctionTemplateDecl>(Orig);
- if (FunctionTemplate)
- Function = cast<T>(FunctionTemplate->getTemplatedDecl());
- else
- Function = cast<T>(Orig);
-}
-
/// Determines whether there is a user-defined conversion sequence
/// (C++ [over.ics.user]) that converts expression From to the type
/// ToType. If such a conversion exists, User will contain the
@@ -1455,18 +1443,16 @@
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
- OverloadedFunctionDecl *Conversions
+ const UnresolvedSet *Conversions
= FromRecordDecl->getVisibleConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator Func
- = Conversions->function_begin();
- Func != Conversions->function_end(); ++Func) {
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
- GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
- if (ConvTemplate)
+ if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(*I)))
Conv = dyn_cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
- Conv = dyn_cast<CXXConversionDecl>(*Func);
+ Conv = dyn_cast<CXXConversionDecl>(*I);
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
@@ -3144,20 +3130,17 @@
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- OverloadedFunctionDecl *Conversions
+ const UnresolvedSet *Conversions
= ClassDecl->getVisibleConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator Func
- = Conversions->function_begin();
- Func != Conversions->function_end(); ++Func) {
- CXXConversionDecl *Conv;
- FunctionTemplateDecl *ConvTemplate;
- GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
// Skip conversion function templates; they don't tell us anything
// about which builtin types we can convert to.
- if (ConvTemplate)
+ if (isa<FunctionTemplateDecl>(*I))
continue;
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
if (AllowExplicitConversions || !Conv->isExplicit()) {
AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
VisibleQuals);
@@ -3211,13 +3194,12 @@
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- OverloadedFunctionDecl *Conversions =
+ const UnresolvedSet *Conversions =
ClassDecl->getVisibleConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator Func
- = Conversions->function_begin();
- Func != Conversions->function_end(); ++Func) {
- if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*Func)) {
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*I)) {
QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
CanTy = ResTypeRef->getPointeeType();
@@ -4336,7 +4318,6 @@
return 0;
// Find the actual overloaded function declaration.
- OverloadedFunctionDecl *Ovl = 0;
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
@@ -4354,15 +4335,21 @@
bool HasExplicitTemplateArgs = false;
const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
+
+ llvm::SmallVector<NamedDecl*,8> Fns;
// Try to dig out the overloaded function.
+ OverloadedFunctionDecl *Ovl = 0;
FunctionTemplateDecl *FunctionTemplate = 0;
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
- Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
+ assert(!isa<OverloadedFunctionDecl>(DR->getDecl()));
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
ExplicitTemplateArgs = DR->getTemplateArgs();
NumExplicitTemplateArgs = DR->getNumTemplateArgs();
+ } else if (UnresolvedLookupExpr *UL
+ = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
+ Fns.append(UL->decls_begin(), UL->decls_end());
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
@@ -4379,23 +4366,20 @@
ExplicitTemplateArgs = TIRE->getTemplateArgs();
NumExplicitTemplateArgs = TIRE->getNumTemplateArgs();
}
-
- // If there's no overloaded function declaration or function template,
- // we're done.
- if (!Ovl && !FunctionTemplate)
- return 0;
- OverloadIterator Fun;
- if (Ovl)
- Fun = Ovl;
- else
- Fun = FunctionTemplate;
+ 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;
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
llvm::SmallPtrSet<FunctionDecl *, 4> Matches;
bool FoundNonTemplateFunction = false;
- for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
+ E = Fns.end(); I != E; ++I) {
// C++ [over.over]p3:
// Non-member functions and static member functions match
// targets of type "pointer-to-function" or "reference-to-function."
@@ -4404,7 +4388,7 @@
// Note that according to DR 247, the containing class does not matter.
if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(*Fun)) {
+ = dyn_cast<FunctionTemplateDecl>(*I)) {
if (CXXMethodDecl *Method
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
// Skip non-static function templates when converting to pointer, and
@@ -4438,9 +4422,11 @@
Matches.insert(
cast<FunctionDecl>(Specialization->getCanonicalDecl()));
}
+
+ continue;
}
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun)) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I)) {
// Skip non-static functions when converting to pointer, and static
// when converting to member pointer.
if (Method->isStatic() == IsMember)
@@ -4452,9 +4438,9 @@
} else if (IsMember)
continue;
- if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
+ if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*I)) {
if (FunctionType == Context.getCanonicalType(FunDecl->getType())) {
- Matches.insert(cast<FunctionDecl>(Fun->getCanonicalDecl()));
+ Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl()));
FoundNonTemplateFunction = true;
}
}
@@ -4522,7 +4508,7 @@
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
- AnyFunctionDecl Callee,
+ NamedDecl *Callee,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
const TemplateArgumentLoc *ExplicitTemplateArgs,
@@ -4530,6 +4516,9 @@
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
+ if (isa<UsingShadowDecl>(Callee))
+ Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
+
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
assert(!HasExplicitTemplateArgs && "Explicit template arguments?");
S.AddOverloadCandidate(Func, Args, NumArgs, CandidateSet, false, false,
@@ -4539,21 +4528,28 @@
Func->getDeclContext()->isFunctionOrMethod())
ArgumentDependentLookup = false;
return;
- }
-
- FunctionTemplateDecl *FuncTemplate = cast<FunctionTemplateDecl>(Callee);
- S.AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs,
- ExplicitTemplateArgs,
- NumExplicitTemplateArgs,
- Args, NumArgs, CandidateSet);
-
- if (FuncTemplate->getDeclContext()->isRecord())
- ArgumentDependentLookup = false;
+ }
+
+ if (FunctionTemplateDecl *FuncTemplate
+ = dyn_cast<FunctionTemplateDecl>(Callee)) {
+ S.AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ Args, NumArgs, CandidateSet);
+
+ if (FuncTemplate->getDeclContext()->isRecord())
+ ArgumentDependentLookup = false;
+ return;
+ }
+
+ assert(false && "unhandled case in overloaded call candidate");
+
+ // do nothing?
}
/// \brief Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
-void Sema::AddOverloadedCallCandidates(NamedDecl *Callee,
+void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns,
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
@@ -4562,11 +4558,11 @@
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
- // Add the functions denoted by Callee to the set of candidate
- // functions. While we're doing so, track whether argument-dependent
- // lookup still applies, per:
+
+#ifndef NDEBUG
+ // Verify that ArgumentDependentLookup is consistent with the rules
+ // in C++0x [basic.lookup.argdep]p3:
//
- // C++0x [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
// lookup (defined as follows). If X contains
@@ -4574,38 +4570,31 @@
// -- a declaration of a class member, or
//
// -- a block-scope function declaration that is not a
- // using-declaration (FIXME: check for using declaration), or
+ // using-declaration, or
//
// -- a declaration that is neither a function or a function
// template
//
// then Y is empty.
- if (!Callee) {
- // Nothing to do.
- } else if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(Callee)) {
- for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
- FuncEnd = Ovl->function_end();
- Func != FuncEnd; ++Func)
- AddOverloadedCallCandidate(*this, *Func, ArgumentDependentLookup,
- HasExplicitTemplateArgs,
- ExplicitTemplateArgs, NumExplicitTemplateArgs,
- Args, NumArgs, CandidateSet,
- PartialOverloading);
- } else if (isa<FunctionDecl>(Callee) || isa<FunctionTemplateDecl>(Callee))
- AddOverloadedCallCandidate(*this,
- AnyFunctionDecl::getFromNamedDecl(Callee),
- ArgumentDependentLookup,
+
+ if (ArgumentDependentLookup) {
+ for (unsigned I = 0; I < Fns.size(); ++I) {
+ assert(!Fns[I]->getDeclContext()->isRecord());
+ assert(isa<UsingShadowDecl>(Fns[I]) ||
+ !Fns[I]->getDeclContext()->isFunctionOrMethod());
+ assert(Fns[I]->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
+ }
+ }
+#endif
+
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
+ E = Fns.end(); I != E; ++I)
+ AddOverloadedCallCandidate(*this, *I, ArgumentDependentLookup,
HasExplicitTemplateArgs,
ExplicitTemplateArgs, NumExplicitTemplateArgs,
- Args, NumArgs, CandidateSet,
+ Args, NumArgs, CandidateSet,
PartialOverloading);
- // FIXME: assert isa<FunctionDecl> || isa<FunctionTemplateDecl> rather than
- // checking dynamically.
-
- if (Callee)
- UnqualifiedName = Callee->getDeclName();
-
+
if (ArgumentDependentLookup)
AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
HasExplicitTemplateArgs,
@@ -4622,7 +4611,8 @@
/// the function declaration produced by overload
/// resolution. Otherwise, emits diagnostics, deletes all of the
/// arguments and Fn, and returns NULL.
-FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
+FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn,
+ llvm::SmallVectorImpl<NamedDecl*> &Fns,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
const TemplateArgumentLoc *ExplicitTemplateArgs,
@@ -4636,7 +4626,7 @@
// Add the functions denoted by Callee to the set of candidate
// functions.
- AddOverloadedCallCandidates(Callee, UnqualifiedName, ArgumentDependentLookup,
+ AddOverloadedCallCandidates(Fns, UnqualifiedName, ArgumentDependentLookup,
HasExplicitTemplateArgs, ExplicitTemplateArgs,
NumExplicitTemplateArgs, Args, NumArgs,
CandidateSet);
@@ -4716,15 +4706,13 @@
}
if (Input->isTypeDependent()) {
- OverloadedFunctionDecl *Overloads
- = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc,
+ /*ADL*/ true);
for (FunctionSet::iterator Func = Functions.begin(),
FuncEnd = Functions.end();
Func != FuncEnd; ++Func)
- Overloads->addOverload(*Func);
-
- DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
- OpLoc, false, false);
+ Fn->addDecl(*Func);
input.release();
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
@@ -4874,15 +4862,14 @@
OpLoc));
}
- OverloadedFunctionDecl *Overloads
- = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc,
+ /* ADL */ true);
+
for (FunctionSet::iterator Func = Functions.begin(),
FuncEnd = Functions.end();
Func != FuncEnd; ++Func)
- Overloads->addOverload(*Func);
-
- DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
- OpLoc, false, false);
+ Fn->addDecl(*Func);
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
Args, 2,
@@ -5040,11 +5027,10 @@
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- OverloadedFunctionDecl *Overloads
- = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
-
- DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
- LLoc, false, false);
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, LLoc,
+ /*ADL*/ true);
+ // Can't add an actual overloads yet
Base.release();
Idx.release();
@@ -5334,21 +5320,17 @@
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
// FIXME: Look in base classes for more conversion operators!
- OverloadedFunctionDecl *Conversions
+ const UnresolvedSet *Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Func = Conversions->function_begin(),
- FuncEnd = Conversions->function_end();
- Func != FuncEnd; ++Func) {
- CXXConversionDecl *Conv;
- FunctionTemplateDecl *ConvTemplate;
- GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
-
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
// Skip over templated conversion functions; they aren't
// surrogates.
- if (ConvTemplate)
+ if (isa<FunctionTemplateDecl>(*I))
continue;
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I);
+
// Strip the reference type (if any) and then the pointer type (if
// any) to get down to what might be a function type.
QualType ConvType = Conv->getConversionType().getNonReferenceType();
@@ -5637,38 +5619,32 @@
if (Method->isStatic()) {
// Do nothing: static member functions aren't any different
// from non-member functions.
- } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) {
- if (DRE->getQualifier()) {
- // We have taken the address of a pointer to member
- // function. Perform the computation here so that we get the
- // appropriate pointer to member type.
- QualType ClassType
- = Context.getTypeDeclType(
- cast<RecordDecl>(Method->getDeclContext()));
- QualType MemPtrType
- = Context.getMemberPointerType(Fn->getType(),
- ClassType.getTypePtr());
-
- DeclRefExpr *NewDRE
- = DeclRefExpr::Create(Context,
- DRE->getQualifier(),
- DRE->getQualifierRange(),
- Fn,
- DRE->getLocation(),
- DRE->hasExplicitTemplateArgumentList(),
- DRE->getLAngleLoc(),
- DRE->getTemplateArgs(),
- DRE->getNumTemplateArgs(),
- DRE->getRAngleLoc(),
- Fn->getType(),
- DRE->isTypeDependent(),
- DRE->isValueDependent());
-
- return new (Context) UnaryOperator(NewDRE, UnaryOperator::AddrOf,
- MemPtrType,
- UnOp->getOperatorLoc());
- }
+ } else {
+ // Fix the sub expression, which really has to be one of:
+ // * a DeclRefExpr holding a member function template
+ // * a TemplateIdRefExpr, also holding a member function template
+ // * an UnresolvedLookupExpr holding an overloaded member function
+ Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+ if (SubExpr == UnOp->getSubExpr())
+ return UnOp->Retain();
+
+ assert(isa<DeclRefExpr>(SubExpr)
+ && "fixed to something other than a decl ref");
+ assert(cast<DeclRefExpr>(SubExpr)->getQualifier()
+ && "fixed to a member ref with no nested name qualifier");
+
+ // We have taken the address of a pointer to member
+ // function. Perform the computation here so that we get the
+ // appropriate pointer to member type.
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ QualType MemPtrType
+ = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+
+ return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+ MemPtrType, UnOp->getOperatorLoc());
}
+
// FIXME: TemplateIdRefExpr referring to a member function template
// specialization!
}
@@ -5682,8 +5658,7 @@
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- assert((isa<OverloadedFunctionDecl>(DRE->getDecl()) ||
- isa<FunctionTemplateDecl>(DRE->getDecl()) ||
+ assert((isa<FunctionTemplateDecl>(DRE->getDecl()) ||
isa<FunctionDecl>(DRE->getDecl())) &&
"Expected function or function template");
return DeclRefExpr::Create(Context,
@@ -5700,6 +5675,18 @@
DRE->isTypeDependent(),
DRE->isValueDependent());
}
+
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ return DeclRefExpr::Create(Context,
+ ULE->getQualifier(),
+ ULE->getQualifierRange(),
+ Fn,
+ ULE->getNameLoc(),
+ Fn->getType(),
+ Fn->getType()->isDependentType(),
+ false);
+ }
+
if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
assert((isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
@@ -5736,13 +5723,6 @@
/*FIXME?*/false, /*FIXME?*/false);
}
- if (isa<UnresolvedFunctionNameExpr>(E))
- return DeclRefExpr::Create(Context,
- /*Qualifier=*/0,
- /*QualifierRange=*/SourceRange(),
- Fn, E->getLocStart(),
- Fn->getType(), false, false);
-
assert(false && "Invalid reference to overloaded function");
return E->Retain();
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sat Nov 21 02:51:07 2009
@@ -556,6 +556,9 @@
bool isAddressOfOperand);
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
bool isAddressOfOperand);
+ Sema::OwningExprResult TransformUnresolvedLookupExpr(
+ UnresolvedLookupExpr *E,
+ bool isAddressOfOperand);
Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
bool isAddressOfOperand);
@@ -694,6 +697,55 @@
}
Sema::OwningExprResult
+TemplateInstantiator::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
+ bool isAddressOfOperand) {
+ llvm::SmallVector<NamedDecl*, 16> InstDecls;
+
+ bool HasUnresolved = false;
+
+ for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
+ E = Old->decls_end(); I != E; ++I) {
+ NamedDecl *InstD = SemaRef.FindInstantiatedDecl(*I, TemplateArgs);
+ if (!InstD)
+ return SemaRef.ExprError();
+
+ // Expand using declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+ for (UsingDecl::shadow_iterator UI = UD->shadow_begin(),
+ UE = UD->shadow_end(); UI != UE; ++UI) {
+ UsingShadowDecl *Shadow = *UI;
+ if (isa<UnresolvedUsingValueDecl>(Shadow->getUnderlyingDecl()))
+ HasUnresolved = true;
+ InstDecls.push_back(Shadow);
+ }
+
+ continue;
+ }
+
+ if (isa<UnresolvedUsingValueDecl>(InstD->getUnderlyingDecl()))
+ HasUnresolved = true;
+ InstDecls.push_back(InstD);
+ }
+
+ CXXScopeSpec SS;
+ NestedNameSpecifier *Qualifier = 0;
+ if (Old->getQualifier()) {
+ Qualifier = TransformNestedNameSpecifier(Old->getQualifier(),
+ Old->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+
+ SS.setScopeRep(Qualifier);
+ SS.setRange(Old->getQualifierRange());
+ }
+
+ return SemaRef.BuildDeclarationNameExpr(&SS, Old->getNameLoc(),
+ Old->getName(), Old->requiresADL(),
+ InstDecls.data(), InstDecls.size());
+}
+
+Sema::OwningExprResult
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
bool isAddressOfOperand) {
// FIXME: Clean this up a bit
@@ -788,46 +840,7 @@
if (!InstD)
return SemaRef.ExprError();
- // Flatten using declarations into their shadow declarations.
- if (isa<UsingDecl>(InstD)) {
- UsingDecl *UD = cast<UsingDecl>(InstD);
-
- bool HasNonFunction = false;
-
- llvm::SmallVector<NamedDecl*, 8> Decls;
- for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
- E = UD->shadow_end(); I != E; ++I) {
- NamedDecl *TD = (*I)->getTargetDecl();
- if (!TD->isFunctionOrFunctionTemplate())
- HasNonFunction = true;
-
- Decls.push_back(TD);
- }
-
- if (Decls.empty())
- return SemaRef.ExprError();
-
- if (Decls.size() == 1)
- InstD = Decls[0];
- else if (!HasNonFunction) {
- OverloadedFunctionDecl *OFD
- = OverloadedFunctionDecl::Create(SemaRef.Context,
- UD->getDeclContext(),
- UD->getDeclName());
- for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(),
- E = Decls.end(); I != E; ++I)
- if (isa<FunctionDecl>(*I))
- OFD->addOverload(cast<FunctionDecl>(*I));
- else
- OFD->addOverload(cast<FunctionTemplateDecl>(*I));
-
- InstD = OFD;
- } else {
- // FIXME
- assert(false && "using declaration resolved to mixed set");
- return SemaRef.ExprError();
- }
- }
+ assert(!isa<UsingDecl>(InstD) && "decl ref instantiated to UsingDecl");
CXXScopeSpec SS;
NestedNameSpecifier *Qualifier = 0;
@@ -841,10 +854,7 @@
SS.setRange(E->getQualifierRange());
}
- return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD,
- /*FIXME:*/false,
- &SS,
- isAddressOfOperand);
+ return SemaRef.BuildDeclarationNameExpr(&SS, E->getLocation(), InstD);
}
Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sat Nov 21 02:51:07 2009
@@ -4558,10 +4558,10 @@
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr(
- UnresolvedFunctionNameExpr *E,
+TreeTransform<Derived>::TransformUnresolvedLookupExpr(
+ UnresolvedLookupExpr *E,
bool isAddressOfOperand) {
- // There is no transformation we can apply to an unresolved function name.
+ // There is no transformation we can apply to an unresolved lookup.
return SemaRef.Owned(E->Retain());
}
@@ -5384,8 +5384,7 @@
ExprArg Second) {
Expr *FirstExpr = (Expr *)First.get();
Expr *SecondExpr = (Expr *)Second.get();
- DeclRefExpr *DRE
- = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts());
+ Expr *CalleeExpr = ((Expr *)Callee.get())->IgnoreParenCasts();
bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
// Determine whether this should be a builtin operation.
@@ -5393,7 +5392,7 @@
if (!FirstExpr->getType()->isOverloadableType() &&
!SecondExpr->getType()->isOverloadableType())
return getSema().CreateBuiltinArraySubscriptExpr(move(First),
- DRE->getLocStart(),
+ CalleeExpr->getLocStart(),
move(Second), OpLoc);
} else if (Op == OO_Arrow) {
// -> is never a builtin operation.
@@ -5428,10 +5427,18 @@
// used during overload resolution.
Sema::FunctionSet Functions;
- // FIXME: Do we have to check
- // IsAcceptableNonMemberOperatorCandidate for each of these?
- for (OverloadIterator F(DRE->getDecl()), FEnd; F != FEnd; ++F)
- Functions.insert(*F);
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) {
+ assert(ULE->requiresADL());
+
+ // FIXME: Do we have to check
+ // IsAcceptableNonMemberOperatorCandidate for each of these?
+ for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+ E = ULE->decls_end(); I != E; ++I)
+ Functions.insert(AnyFunctionDecl::getFromNamedDecl(*I));
+ } else {
+ Functions.insert(AnyFunctionDecl::getFromNamedDecl(
+ cast<DeclRefExpr>(CalleeExpr)->getDecl()));
+ }
// Add any functions found via argument-dependent lookup.
Expr *Args[2] = { FirstExpr, SecondExpr };
@@ -5449,8 +5456,10 @@
}
if (Op == OO_Subscript)
- return SemaRef.CreateOverloadedArraySubscriptExpr(DRE->getLocStart(), OpLoc,
- move(First),move(Second));
+ return SemaRef.CreateOverloadedArraySubscriptExpr(CalleeExpr->getLocStart(),
+ OpLoc,
+ move(First),
+ move(Second));
// Create the overloaded operator invocation for binary operators.
BinaryOperator::Opcode Opc =
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp Sat Nov 21 02:51:07 2009
@@ -41,8 +41,8 @@
void m()
{
- void f(int, int); // expected-note{{candidate}}
- f(4); // expected-error{{no matching}}
+ void f(int, int);
+ f(4); // expected-error{{too few arguments to function call}}
void f(int, int = 5); // expected-note{{previous definition}}
f(4); // okay
void f(int, int = 5); // expected-error{{redefinition of default argument}}
Modified: cfe/trunk/test/SemaObjC/ivar-ref-misuse.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-ref-misuse.m?rev=89544&r1=89543&r2=89544&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/ivar-ref-misuse.m (original)
+++ cfe/trunk/test/SemaObjC/ivar-ref-misuse.m Sat Nov 21 02:51:07 2009
@@ -15,7 +15,7 @@
@implementation Sprite
+ (void)setFoo:(int)foo {
- sprite = foo; // expected-error {{use of undeclared identifier 'sprite'}}
+ sprite = foo; // expected-error {{instance variable 'sprite' accessed in class method}}
spree = foo;
Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}}
UseGlobalBar = 10;
More information about the cfe-commits
mailing list