diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 5 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 11 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 35 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 4 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 3 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 42 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 154 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 903 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.h | 199 |
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 |