aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-10-21 16:13:35 +0000
committerDouglas Gregor <dgregor@apple.com>2008-10-21 16:13:35 +0000
commit8e9bebdea69c590dedfbf27374114cb76fe12fbd (patch)
treea23d60f1da3648dcff20b6db034b2f5bf30ac50f
parent6d34893fc886f4153f104de8880876764981cb7f (diff)
Preliminary support for function overloading
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57909 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Driver/RewriteObjC.cpp3
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/DeclBase.h2
-rw-r--r--include/clang/AST/DeclCXX.h82
-rw-r--r--include/clang/AST/Expr.h11
-rw-r--r--include/clang/AST/Type.h4
-rw-r--r--include/clang/Analysis/Support/ExprDeclBitVector.h12
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h3
-rw-r--r--include/clang/Basic/DiagnosticKinds.def14
-rw-r--r--lib/AST/ASTContext.cpp5
-rw-r--r--lib/AST/DeclBase.cpp11
-rw-r--r--lib/AST/DeclCXX.cpp7
-rw-r--r--lib/AST/DeclSerialization.cpp35
-rw-r--r--lib/AST/StmtSerialization.cpp4
-rw-r--r--lib/AST/Type.cpp3
-rw-r--r--lib/Analysis/BasicStore.cpp4
-rw-r--r--lib/Analysis/GRExprEngine.cpp2
-rw-r--r--lib/Analysis/RegionStore.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp4
-rw-r--r--lib/Sema/IdentifierResolver.cpp4
-rw-r--r--lib/Sema/Sema.h42
-rw-r--r--lib/Sema/SemaDecl.cpp154
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp84
-rw-r--r--lib/Sema/SemaOverload.cpp903
-rw-r--r--lib/Sema/SemaOverload.h199
-rw-r--r--test/SemaCXX/overload-call.cpp137
-rw-r--r--test/SemaCXX/overload-decl.cpp29
28 files changed, 1704 insertions, 64 deletions
diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp
index 14f6ade591..821bf2d9c3 100644
--- a/Driver/RewriteObjC.cpp
+++ b/Driver/RewriteObjC.cpp
@@ -1178,7 +1178,8 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
elementName = DR->getDecl()->getName();
- elementTypeAsString = DR->getDecl()->getType().getAsString();
+ elementTypeAsString
+ = cast<ValueDecl>(DR->getDecl())->getType().getAsString();
}
// struct __objcFastEnumerationState enumState = { 0 };
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 779f318b5e..6ca92df0e5 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -137,7 +137,8 @@ public:
QualType FloatTy, DoubleTy, LongDoubleTy;
QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
QualType VoidPtrTy;
-
+ QualType OverloadTy;
+
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
unsigned size_reserve=0);
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index a1239deea4..fd5ce41495 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -48,6 +48,7 @@ public:
CXXField,
ObjCIvar,
ObjCAtDefsField,
+ OverloadedFunction,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
@@ -178,6 +179,7 @@ public:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
+ case OverloadedFunction:
case CXXField:
case CXXMethod:
case CXXClassVar:
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 2ce4956a1d..ae16d99c8b 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1,4 +1,4 @@
-//===-- DeclCXX.h - Classes for representing C++ declarations *- C++ -*-======//
+//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====//
//
// The LLVM Compiler Infrastructure
//
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLCXX_H
#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
namespace clang {
class CXXRecordDecl;
@@ -191,6 +192,85 @@ public:
}
};
+/// 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.
+///
+/// An OverloadedFunctionDecl has no ownership over the FunctionDecl
+/// nodes it contains. Rather, the FunctionDecls are owned by the
+/// enclosing scope (which also owns the OverloadedFunctionDecl
+/// node). OverloadedFunctionDecl is used primarily to store a set of
+/// overloaded functions for name lookup.
+class OverloadedFunctionDecl : public NamedDecl {
+protected:
+ OverloadedFunctionDecl(DeclContext *DC, IdentifierInfo *Id)
+ : NamedDecl(OverloadedFunction, SourceLocation(), Id) { }
+
+ /// Functions - the set of overloaded functions contained in this
+ /// overload set.
+ llvm::SmallVector<FunctionDecl *, 4> Functions;
+
+public:
+ typedef llvm::SmallVector<FunctionDecl *, 4>::iterator function_iterator;
+ typedef llvm::SmallVector<FunctionDecl *, 4>::const_iterator
+ function_const_iterator;
+
+ static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ IdentifierInfo *Id);
+
+ /// addOverload - Add an overloaded function FD to this set of
+ /// overloaded functions.
+ void addOverload(FunctionDecl *FD) {
+ assert((!getNumFunctions() || (FD->getDeclContext() == getDeclContext())) &&
+ "Overloaded functions must all be in the same context");
+ assert(FD->getIdentifier() == getIdentifier() &&
+ "Overloaded functions must have the same name.");
+ Functions.push_back(FD);
+ }
+
+ function_iterator function_begin() { return Functions.begin(); }
+ function_iterator function_end() { return Functions.end(); }
+ function_const_iterator function_begin() const { return Functions.begin(); }
+ function_const_iterator function_end() const { return Functions.end(); }
+
+ /// getNumFunctions - the number of overloaded functions stored in
+ /// this set.
+ unsigned getNumFunctions() const { return Functions.size(); }
+
+ /// getFunction - retrieve the ith function in the overload set.
+ const FunctionDecl *getFunction(unsigned i) const {
+ assert(i < getNumFunctions() && "Illegal function #");
+ return Functions[i];
+ }
+ FunctionDecl *getFunction(unsigned i) {
+ assert(i < getNumFunctions() && "Illegal function #");
+ return Functions[i];
+ }
+
+ // getDeclContext - Get the context of these overloaded functions.
+ DeclContext *getDeclContext() {
+ assert(getNumFunctions() > 0 && "Context of an empty overload set");
+ return getFunction(0)->getDeclContext();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == OverloadedFunction;
+ }
+ static bool classof(const OverloadedFunctionDecl *D) { return true; }
+
+protected:
+ /// EmitImpl - Serialize this FunctionDecl. Called by Decl::Emit.
+ virtual void EmitImpl(llvm::Serializer& S) const;
+
+ /// CreateImpl - Deserialize an OverloadedFunctionDecl. Called by
+ /// Decl::Create.
+ static OverloadedFunctionDecl* CreateImpl(llvm::Deserializer& D,
+ ASTContext& C);
+
+ friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index d11c1aa287..de4f4f75bb 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -27,6 +27,7 @@ namespace clang {
class Decl;
class IdentifierInfo;
class ParmVarDecl;
+ class NamedDecl;
class ValueDecl;
class BlockDecl;
@@ -214,19 +215,19 @@ public:
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
/// enum, etc.
class DeclRefExpr : public Expr {
- ValueDecl *D;
+ NamedDecl *D;
SourceLocation Loc;
protected:
- DeclRefExpr(StmtClass SC, ValueDecl *d, QualType t, SourceLocation l) :
+ DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
Expr(SC, t), D(d), Loc(l) {}
public:
- DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) :
+ DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
Expr(DeclRefExprClass, t), D(d), Loc(l) {}
- ValueDecl *getDecl() { return D; }
- const ValueDecl *getDecl() const { return D; }
+ NamedDecl *getDecl() { return D; }
+ const NamedDecl *getDecl() const { return D; }
SourceLocation getLocation() const { return Loc; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index a863e400ae..e2ba317d05 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -494,7 +494,9 @@ public:
Long,
LongLong,
- Float, Double, LongDouble
+ Float, Double, LongDouble,
+
+ Overload // This represents the type of an overloaded function declaration.
};
private:
Kind TypeKind;
diff --git a/include/clang/Analysis/Support/ExprDeclBitVector.h b/include/clang/Analysis/Support/ExprDeclBitVector.h
index 7b44fd7c6b..362ce161ab 100644
--- a/include/clang/Analysis/Support/ExprDeclBitVector.h
+++ b/include/clang/Analysis/Support/ExprDeclBitVector.h
@@ -18,14 +18,14 @@
#define LLVM_CLANG_EXPRDECLBVDVAL_H
#include "clang/AST/CFG.h"
+#include "clang/AST/Decl.h" // for ScopedDecl* -> NamedDecl* conversion
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class Expr;
- class ScopedDecl;
-
+
struct DeclBitVector_Types {
class Idx {
@@ -49,7 +49,7 @@ struct DeclBitVector_Types {
class AnalysisDataTy {
public:
- typedef llvm::DenseMap<const ScopedDecl*, unsigned > DMapTy;
+ typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
typedef DMapTy::const_iterator decl_iterator;
protected:
@@ -61,16 +61,16 @@ struct DeclBitVector_Types {
AnalysisDataTy() : NDecls(0) {}
virtual ~AnalysisDataTy() {}
- bool isTracked(const ScopedDecl* SD) { return DMap.find(SD) != DMap.end(); }
+ bool isTracked(const NamedDecl* SD) { return DMap.find(SD) != DMap.end(); }
- Idx getIdx(const ScopedDecl* SD) const {
+ Idx getIdx(const NamedDecl* SD) const {
DMapTy::const_iterator I = DMap.find(SD);
return I == DMap.end() ? Idx() : Idx(I->second);
}
unsigned getNumDecls() const { return NDecls; }
- void Register(const ScopedDecl* SD) {
+ void Register(const NamedDecl* SD) {
if (!isTracked(SD)) DMap[SD] = NDecls++;
}
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index e24359d4ac..322070b380 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -37,7 +37,8 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
public:
void VisitDeclRefExpr(DeclRefExpr* DR) {
- for (ScopedDecl* D = DR->getDecl(); D != NULL; D = D->getNextDeclarator())
+ for (ScopedDecl* D = dyn_cast<ScopedDecl>(DR->getDecl()); D != NULL;
+ D = D->getNextDeclarator())
static_cast<ImplClass*>(this)->VisitScopedDecl(D);
}
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 474beeb31c..352cc91de4 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -800,6 +800,20 @@ DIAG(err_previous_use, ERROR,
DIAG(err_first_label, ERROR,
"first label is here")
+// C++ Overloading Semantic Analysis.
+DIAG(err_ovl_diff_return_type, ERROR,
+ "functions that differ only in their return type cannot be overloaded")
+DIAG(err_ovl_static_nonstatic_member, ERROR,
+ "static and non-static member functions with the same parameter types cannot be overloaded")
+DIAG(err_ovl_no_viable_function_in_call, ERROR,
+ "no matching function for call to '%0'.")
+DIAG(err_ovl_no_viable_function_in_call_with_cands, ERROR,
+ "no matching function for call to '%0'; candidates are:")
+DIAG(err_ovl_ambiguous_call, ERROR,
+ "call to '%0' is ambiguous; candidates are:")
+DIAG(err_ovl_candidate, NOTE,
+ "candidate function")
+
DIAG(err_unexpected_typedef, ERROR,
"unexpected type name '%0': expected expression")
DIAG(err_unexpected_namespace, ERROR,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f4266fb90d..cbbfe317d5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -182,11 +182,14 @@ void ASTContext::InitBuiltinTypes() {
// C++ 3.9.1p5
InitBuiltinType(WCharTy, BuiltinType::WChar);
+ // Placeholder type for functions.
+ InitBuiltinType(OverloadTy, BuiltinType::Overload);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
LongDoubleComplexTy = getComplexType(LongDoubleTy);
-
+
BuiltinVaListType = QualType();
ObjCIdType = QualType();
IdStructType = 0;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 75d6bc6ce9..686aba2460 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -31,6 +31,7 @@ static unsigned nCXXSUC = 0;
static unsigned nEnumConst = 0;
static unsigned nEnumDecls = 0;
static unsigned nNamespaces = 0;
+static unsigned nOverFuncs = 0;
static unsigned nTypedef = 0;
static unsigned nFieldDecls = 0;
static unsigned nCXXFieldDecls = 0;
@@ -63,6 +64,7 @@ const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Unknown decl kind!");
case Namespace: return "Namespace";
+ case OverloadedFunction: return "OverloadedFunction";
case Typedef: return "Typedef";
case Function: return "Function";
case Var: return "Var";
@@ -93,10 +95,13 @@ void Decl::PrintStats() {
int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXFieldDecls+nCXXSUC+
nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
- nAtDefsFieldDecls+nNamespaces));
+ nAtDefsFieldDecls+nNamespaces+nOverFuncs));
fprintf(stderr, " %d namespace decls, %d each (%d bytes)\n",
nNamespaces, (int)sizeof(NamespaceDecl),
int(nNamespaces*sizeof(NamespaceDecl)));
+ fprintf(stderr, " %d overloaded function decls, %d each (%d bytes)\n",
+ nOverFuncs, (int)sizeof(OverloadedFunctionDecl),
+ int(nOverFuncs*sizeof(OverloadedFunctionDecl)));
fprintf(stderr, " %d function decls, %d each (%d bytes)\n",
nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
fprintf(stderr, " %d variable decls, %d each (%d bytes)\n",
@@ -192,13 +197,15 @@ void Decl::PrintStats() {
nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)+
nLinkageSpecDecl*sizeof(LinkageSpecDecl)+
nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)+
- nNamespaces*sizeof(NamespaceDecl)));
+ nNamespaces*sizeof(NamespaceDecl)+
+ nOverFuncs*sizeof(OverloadedFunctionDecl)));
}
void Decl::addDeclKind(Kind k) {
switch (k) {
case Namespace: nNamespaces++; break;
+ case OverloadedFunction: nOverFuncs++; break;
case Typedef: nTypedef++; break;
case Function: nFuncs++; break;
case Var: nVars++; break;
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index af89da44cc..9fd7ff974e 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -59,3 +59,10 @@ CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
}
+
+OverloadedFunctionDecl *
+OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
+ IdentifierInfo *Id) {
+ void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
+ return new (Mem) OverloadedFunctionDecl(DC, Id);
+}
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index a0befbdbb0..f2aa3f3027 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
@@ -74,7 +75,11 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) {
case Function:
Dcl = FunctionDecl::CreateImpl(D, C);
break;
-
+
+ case OverloadedFunction:
+ Dcl = OverloadedFunctionDecl::CreateImpl(D, C);
+ break;
+
case Record:
Dcl = RecordDecl::CreateImpl(D, C);
break;
@@ -455,6 +460,34 @@ BlockDecl* BlockDecl::CreateImpl(Deserializer& D, ASTContext& C) {
}
//===----------------------------------------------------------------------===//
+// OverloadedFunctionDecl Serialization.
+//===----------------------------------------------------------------------===//
+
+void OverloadedFunctionDecl::EmitImpl(Serializer& S) const {
+ NamedDecl::EmitInRec(S);
+
+ S.EmitInt(getNumFunctions());
+ for (unsigned func = 0; func < getNumFunctions(); ++func)
+ S.EmitPtr(Functions[func]);
+}
+
+OverloadedFunctionDecl *
+OverloadedFunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
+ void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
+ OverloadedFunctionDecl* decl = new (Mem)
+ OverloadedFunctionDecl(0, NULL);
+
+ decl->NamedDecl::ReadInRec(D, C);
+
+ unsigned numFunctions = D.ReadInt();
+ decl->Functions.reserve(numFunctions);
+ for (unsigned func = 0; func < numFunctions; ++func)
+ D.ReadPtr(decl->Functions[func]);
+
+ return decl;
+}
+
+//===----------------------------------------------------------------------===//
// RecordDecl Serialization.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index baee030144..decd9a76c9 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -522,12 +522,12 @@ DeclRefExpr* DeclRefExpr::CreateImpl(Deserializer& D, ASTContext& C) {
SourceLocation Loc = SourceLocation::ReadVal(D);
QualType T = QualType::ReadVal(D);
bool OwnsDecl = D.ReadBool();
- ValueDecl* decl;
+ NamedDecl* decl;
if (!OwnsDecl)
D.ReadPtr(decl,false); // No backpatching.
else
- decl = cast<ValueDecl>(D.ReadOwnedPtr<Decl>(C));
+ decl = cast<NamedDecl>(D.ReadOwnedPtr<Decl>(C));
return new DeclRefExpr(decl,T,Loc);
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 74e52fef88..5de44762c3 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -450,6 +450,7 @@ bool Type::isIntegerType() const {
BT->getKind() <= BuiltinType::LongLong;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
// Incomplete enum types are not treated as integer types.
+ // FIXME: In C++, enum types are never integer types.
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
@@ -466,6 +467,7 @@ bool Type::isIntegralType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true; // Complete enum types are integral.
+ // FIXME: In C++, enum types are never integral.
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
return ASQT->getBaseType()->isIntegralType();
return false;
@@ -697,6 +699,7 @@ const char *BuiltinType::getName() const {
case Double: return "double";
case LongDouble: return "long double";
case WChar: return "wchar_t";
+ case Overload: return "<overloaded function type>";
}
}
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index b42f210dd8..2a003335b6 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -299,9 +299,9 @@ Store BasicStoreManager::getInitialStore() {
Store St = VBFactory.GetEmptyMap().getRoot();
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
- ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
+ NamedDecl* ND = const_cast<NamedDecl*>(I->first);
- if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
// Punt on static variables for now.
if (VD->getStorageClass() == VarDecl::Static)
continue;
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 68f10b0d03..e6780161d7 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -823,7 +823,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
const GRState* St = GetState(Pred);
- const ValueDecl* D = Ex->getDecl();
+ const NamedDecl* D = Ex->getDecl();
if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index f936fff1b9..9efcc48c51 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -118,9 +118,9 @@ Store RegionStoreManager::getInitialStore() {
Store St = RBFactory.GetEmptyMap().getRoot();
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
- ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
+ NamedDecl* ND = const_cast<NamedDecl*>(I->first);
- if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
// Punt on static variables for now.
if (VD->getStorageClass() == VarDecl::Static)
continue;
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 783bb1c67a..5fc513d125 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -371,7 +371,7 @@ public:
}
llvm::Constant *VisitDeclRefExpr(DeclRefExpr *E) {
- const ValueDecl *Decl = E->getDecl();
+ const NamedDecl *Decl = E->getDecl();
if (const EnumConstantDecl *EC = dyn_cast<EnumConstantDecl>(Decl))
return llvm::ConstantInt::get(EC->getInitVal());
assert(0 && "Unsupported decl ref type!");
@@ -769,7 +769,7 @@ public:
return C;
}
case Expr::DeclRefExprClass: {
- ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
+ NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
return CGM.GetAddrOfFunction(FD);
if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index e97de73817..8375720e55 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -57,7 +57,9 @@ DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
Ctx = EnumD->getDeclContext()->getParent();
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
- Ctx = SD->getDeclContext();
+ Ctx = SD->getDeclContext();
+ else if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
+ Ctx = Ovl->getDeclContext();
else
return TUCtx();
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 796ba4ed04..039571f9fe 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -17,6 +17,7 @@
#include "IdentifierResolver.h"
#include "CXXFieldCollector.h"
+#include "SemaOverload.h"
#include "clang/Parse/Action.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
@@ -361,7 +362,46 @@ private:
VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);
FunctionDecl *MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
void CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD);
-
+
+ /// C++ Overloading.
+ bool IsOverload(FunctionDecl *New, Decl* OldD,
+ OverloadedFunctionDecl::function_iterator &MatchedDecl);
+ ImplicitConversionSequence TryCopyInitialization(Expr* From, QualType ToType);
+ bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
+ bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+ bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ QualType& ConvertedType);
+
+ ImplicitConversionSequence::CompareKind
+ CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
+ const ImplicitConversionSequence& ICS2);
+
+ ImplicitConversionSequence::CompareKind
+ CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+ /// OverloadingResult - Capture the result of performing overload
+ /// resolution.
+ enum OverloadingResult {
+ OR_Success, ///< Overload resolution succeeded.
+ OR_No_Viable_Function, ///< No viable function found.
+ OR_Ambiguous ///< Ambiguous candidates found.
+ };
+
+ void AddOverloadCandidate(FunctionDecl *Function,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ void AddOverloadCandidates(OverloadedFunctionDecl *Ovl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
+ const OverloadCandidate& Cand2);
+ OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet::iterator& Best);
+ void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
+ bool OnlyViable);
+
+
/// Helpers for dealing with function parameters
bool CheckParmsForFunctionDef(FunctionDecl *FD);
void CheckCXXDefaultArguments(FunctionDecl *FD);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e32da244de..1befc2e2e9 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -95,7 +95,41 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
IdResolver.AddShadowedDecl(TD, *I);
return;
}
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // We are pushing the name of a function, which might be an
+ // overloaded name.
+ IdentifierResolver::iterator
+ I = IdResolver.begin(FD->getIdentifier(),
+ FD->getDeclContext(), false/*LookInParentCtx*/);
+ if (I != IdResolver.end() &&
+ IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
+ (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
+ // There is already a declaration with the same name in the same
+ // scope. It must be a function or an overloaded function.
+ OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
+ if (!Ovl) {
+ // We haven't yet overloaded this function. Take the existing
+ // FunctionDecl and put it into an OverloadedFunctionDecl.
+ Ovl = OverloadedFunctionDecl::Create(Context,
+ FD->getDeclContext(),
+ FD->getIdentifier());
+ Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
+
+ // Remove the name binding to the existing FunctionDecl...
+ IdResolver.RemoveDecl(*I);
+
+ // ... and put the OverloadedFunctionDecl in its place.
+ IdResolver.AddDecl(Ovl);
+ }
+
+ // We have an OverloadedFunctionDecl. Add the new FunctionDecl
+ // to its list of overloads.
+ Ovl->addOverload(FD);
+
+ return;
+ }
}
+
IdResolver.AddDecl(D);
}
@@ -320,9 +354,17 @@ static void MergeAttributes(Decl *New, Decl *Old) {
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
/// merging decls or emitting diagnostics as appropriate.
-/// Redeclaration will be set true if thisNew is a redeclaration OldD.
+/// Redeclaration will be set true if this New is a redeclaration OldD.
+///
+/// In C++, New and Old must be declarations that are not
+/// overloaded. Use IsOverload to determine whether New and Old are
+/// overloaded, and to select the Old declaration that New should be
+/// merged with.
FunctionDecl *
Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
+ assert(!isa<OverloadedFunctionDecl>(OldD) &&
+ "Cannot merge with an overloaded function declaration");
+
Redeclaration = false;
// Verify the old decl was also a function.
FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
@@ -332,17 +374,59 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
Diag(OldD->getLocation(), diag::err_previous_definition);
return New;
}
+
+ // Determine whether the previous declaration was a definition,
+ // implicit declaration, or a declaratio