aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
17 files changed, 1420 insertions, 48 deletions
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 declaration.
+ diag::kind PrevDiag;
+ if (Old->isThisDeclarationADefinition())
+ PrevDiag = diag::err_previous_definition;
+ else if (Old->isImplicit())
+ PrevDiag = diag::err_previous_implicit_declaration;
+ else
+ PrevDiag = diag::err_previous_declaration;
QualType OldQType = Context.getCanonicalType(Old->getType());
QualType NewQType = Context.getCanonicalType(New->getType());
- // C++ [dcl.fct]p3:
- // All declarations for a function shall agree exactly in both the
- // return type and the parameter-type-list.
- if (getLangOptions().CPlusPlus && OldQType == NewQType) {
- MergeAttributes(New, Old);
- Redeclaration = true;
- return MergeCXXFunctionDecl(New, Old);
+ if (getLangOptions().CPlusPlus) {
+ // (C++98 13.1p2):
+ // Certain function declarations cannot be overloaded:
+ // -- Function declarations that differ only in the return type
+ // cannot be overloaded.
+ QualType OldReturnType
+ = cast<FunctionType>(OldQType.getTypePtr())->getResultType();
+ QualType NewReturnType
+ = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
+ if (OldReturnType != NewReturnType) {
+ Diag(New->getLocation(), diag::err_ovl_diff_return_type);
+ Diag(Old->getLocation(), PrevDiag);
+ return New;
+ }
+
+ const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+ const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+ if (OldMethod && NewMethod) {
+ // -- Member function declarations with the same name and the
+ // same parameter types cannot be overloaded if any of them
+ // is a static member function declaration.
+ if (OldMethod->isStatic() || NewMethod->isStatic()) {
+ Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+ Diag(Old->getLocation(), PrevDiag);
+ return New;
+ }
+ }
+
+ // (C++98 8.3.5p3):
+ // All declarations for a function shall agree exactly in both the
+ // return type and the parameter-type-list.
+ if (OldQType == NewQType) {
+ // We have a redeclaration.
+ MergeAttributes(New, Old);
+ Redeclaration = true;
+ return MergeCXXFunctionDecl(New, Old);
+ }
+
+ // Fall through for conflicting redeclarations and redefinitions.
}
// C: Function types need to be compatible, not identical. This handles
@@ -356,13 +440,6 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
// A function that has already been declared has been redeclared or defined
// with a different type- show appropriate diagnostic
- diag::kind PrevDiag;
- if (Old->isThisDeclarationADefinition())
- PrevDiag = diag::err_previous_definition;
- else if (Old->isImplicit())
- PrevDiag = diag::err_previous_implicit_declaration;
- else
- PrevDiag = diag::err_previous_declaration;
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
// TODO: This is totally simplistic. It should handle merging functions
@@ -717,10 +794,49 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
if (PrevDecl &&
(!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, CurContext, S))) {
bool Redeclaration = false;
- NewFD = MergeFunctionDecl(NewFD, PrevDecl, Redeclaration);
- if (NewFD == 0) return 0;
- if (Redeclaration) {
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(PrevDecl));
+
+ // If C++, determine whether NewFD is an overload of PrevDecl or
+ // a declaration that requires merging. If it's an overload,
+ // there's no more work to do here; we'll just add the new
+ // function to the scope.
+ OverloadedFunctionDecl::function_iterator MatchedDecl;
+ if (!getLangOptions().CPlusPlus ||
+ !IsOverload(NewFD, PrevDecl, MatchedDecl)) {
+ Decl *OldDecl = PrevDecl;
+
+ // If PrevDecl was an overloaded function, extract the
+ // FunctionDecl that matched.
+ if (isa<OverloadedFunctionDecl>(PrevDecl))
+ OldDecl = *MatchedDecl;
+
+ // NewFD and PrevDecl represent declarations that need to be
+ // merged.
+ NewFD = MergeFunctionDecl(NewFD, OldDecl, Redeclaration);
+
+ if (NewFD == 0) return 0;
+ if (Redeclaration) {
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+
+ if (OldDecl == PrevDecl) {
+ // Remove the name binding for the previous
+ // declaration. We'll add the binding back later, but then
+ // it will refer to the new declaration (which will
+ // contain more information).
+ IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
+ } else {
+ // We need to update the OverloadedFunctionDecl with the
+ // latest declaration of this function, so that name
+ // lookup will always refer to the latest declaration of
+ // this function.
+ *MatchedDecl = NewFD;
+
+ // Add the redeclaration to the current scope, since we'll
+ // be skipping PushOnScopeChains.
+ S->AddDecl(NewFD);
+
+ return NewFD;
+ }
+ }
}
}
New = NewFD;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e06761f1ba..fef205cb11 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Compiler.h"
+#include <algorithm> // for std::equal
using namespace clang;
@@ -58,7 +59,7 @@ namespace {
/// determine whether this declaration can be used in the default
/// argument expression.
bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
- ValueDecl *Decl = DRE->getDecl();
+ NamedDecl *Decl = DRE->getDecl();
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
// C++ [dcl.fct.default]p9
// Default arguments are evaluated each time the function is
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5ff8b0e59f..8c63060b61 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -418,6 +418,9 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
return Diag(Loc, diag::err_unexpected_namespace, II.getName());
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
+ if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
+ return new DeclRefExpr(Ovl, Context.OverloadTy, Loc);
+
ValueDecl *VD = cast<ValueDecl>(D);
// check if referencing an identifier with __attribute__((deprecated)).
@@ -1036,16 +1039,67 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
Expr **Args = reinterpret_cast<Expr**>(args);
assert(Fn && "no function call expression");
FunctionDecl *FDecl = NULL;
+ OverloadedFunctionDecl *Ovl = NULL;
+
+ // If we're directly calling a function or a set of overloaded
+ // functions, get the appropriate declaration.
+ {
+ DeclRefExpr *DRExpr = NULL;
+ if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
+ DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr());
+ else
+ DRExpr = dyn_cast<DeclRefExpr>(Fn);
+
+ if (DRExpr) {
+ FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
+ Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
+ }
+ }
+
+ // If we have a set of overloaded functions, perform overload
+ // resolution to pick the function.
+ if (Ovl) {
+ OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet::iterator Best;
+ AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet);
+ switch (BestViableFunction(CandidateSet, Best)) {
+ case OR_Success:
+ {
+ // Success! Let the remainder of this function build a call to
+ // the function selected by overload resolution.
+ FDecl = Best->Function;
+ Expr *NewFn = new DeclRefExpr(FDecl, FDecl->getType(),
+ Fn->getSourceRange().getBegin());
+ delete Fn;
+ Fn = NewFn;
+ }
+ break;
+
+ case OR_No_Viable_Function:
+ if (CandidateSet.empty())
+ Diag(Fn->getSourceRange().getBegin(),
+ diag::err_ovl_no_viable_function_in_call, Ovl->getName(),
+ Fn->getSourceRange());
+ else {
+ Diag(Fn->getSourceRange().getBegin(),
+ diag::err_ovl_no_viable_function_in_call_with_cands,
+ Ovl->getName(), Fn->getSourceRange());
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ }
+ return true;
+
+ case OR_Ambiguous:
+ Diag(Fn->getSourceRange().getBegin(),
+ diag::err_ovl_ambiguous_call, Ovl->getName(),
+ Fn->getSourceRange());
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ return true;
+ }
+ }
// Promote the function operand.
UsualUnaryConversions(Fn);
- // If we're directly calling a function, get the declaration for
- // that function.
- if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
- if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
- FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
-
// Make the call expr early, before semantic checks. This guarantees cleanup
// of arguments and function on error.
llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
@@ -2338,7 +2392,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
/// - *(x + 1) -> x, if x is an array
/// - &"123"[2] -> 0
/// - & __real__ x -> x
-static ValueDecl *getPrimaryDecl(Expr *E) {
+static NamedDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
@@ -2351,7 +2405,8 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
case Stmt::ArraySubscriptExprClass: {
// &X[4] and &4[X] refers to X if X is not a pointer.
- ValueDecl *VD = getPrimaryDecl(cast<ArraySubscriptExpr>(E)->getBase());
+ NamedDecl *D = getPrimaryDecl(cast<ArraySubscriptExpr>(E)->getBase());
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || VD->getType()->isPointerType())
return 0;
else
@@ -2363,10 +2418,13 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
switch(UO->getOpcode()) {
case UnaryOperator::Deref: {
// *(X + 1) refers to X if X is not a pointer.
- ValueDecl *VD = getPrimaryDecl(UO->getSubExpr());
- if (!VD || VD->getType()->isPointerType())
- return 0;
- return VD;
+ if (NamedDecl *D = getPrimaryDecl(UO->getSubExpr())) {
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (!VD || VD->getType()->isPointerType())
+ return 0;
+ return VD;
+ }
+ return 0;
}
case UnaryOperator::Real:
case UnaryOperator::Imag:
@@ -2420,7 +2478,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
// Technically, there should be a check for array subscript
// expressions here, but the result of one is always an lvalue anyway.
}
- ValueDecl *dcl = getPrimaryDecl(op);
+ NamedDecl *dcl = getPrimaryDecl(op);
Expr::isLvalueResult lval = op->isLvalue(Context);
if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
new file mode 100644
index 0000000000..88c209b6e0
--- /dev/null
+++ b/lib/Sema/SemaOverload.cpp
@@ -0,0 +1,903 @@
+//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ overloading.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+
+namespace clang {
+
+/// GetConversionCategory - Retrieve the implicit conversion
+/// category corresponding to the given implicit conversion kind.
+ImplicitConversionCategory
+GetConversionCategory(ImplicitConversionKind Kind) {
+ static const ImplicitConversionCategory
+ Category[(int)ICK_Num_Conversion_Kinds] = {
+ ICC_Identity,
+ ICC_Lvalue_Transformation,
+ ICC_Lvalue_Transformation,
+ ICC_Lvalue_Transformation,
+ ICC_Qualification_Adjustment,
+ ICC_Promotion,
+ ICC_Promotion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion
+ };
+ return Category[(int)Kind];
+}
+
+/// GetConversionRank - Retrieve the implicit conversion rank
+/// corresponding to the given implicit conversion kind.
+ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
+ static const ImplicitConversionRank
+ Rank[(int)ICK_Num_Conversion_Kinds] = {
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Promotion,
+ ICR_Promotion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion
+ };
+ return Rank[(int)Kind];
+}
+
+/// GetImplicitConversionName - Return the name of this kind of
+/// implicit conversion.
+const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
+ static const char* Name[(int)ICK_Num_Conversion_Kinds] = {
+ "No conversion",
+ "Lvalue-to-rvalue",
+ "Array-to-pointer",
+ "Function-to-pointer",
+ "Qualification",
+ "Integral promotion",
+ "Floating point promotion",
+ "Integral conversion",
+ "Floating conversion",
+ "Floating-integral conversion",
+ "Pointer conversion",
+ "Pointer-to-member conversion",
+ "Boolean conversion"
+ };
+ return Name[Kind];
+}
+
+/// getRank - Retrieve the rank of this standard conversion sequence
+/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the
+/// implicit conversions.
+ImplicitConversionRank StandardConversionSequence::getRank() const {
+ ImplicitConversionRank Rank = ICR_Exact_Match;
+ if (GetConversionRank(First) > Rank)
+ Rank = GetConversionRank(First);
+ if (GetConversionRank(Second) > Rank)
+ Rank = GetConversionRank(Second);
+ if (GetConversionRank(Third) > Rank)
+ Rank = GetConversionRank(Third);
+ return Rank;
+}
+
+/// isPointerConversionToBool - Determines whether this conversion is
+/// a conversion of a pointer or pointer-to-member to bool. This is
+/// used as p