diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-10-21 16:13:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-10-21 16:13:35 +0000 |
commit | 8e9bebdea69c590dedfbf27374114cb76fe12fbd (patch) | |
tree | a23d60f1da3648dcff20b6db034b2f5bf30ac50f | |
parent | 6d34893fc886f4153f104de8880876764981cb7f (diff) |
Preliminary support for function overloading
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57909 91177308-0d34-0410-b5e6-96231b3b80d8
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 |