diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-04-16 17:51:27 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-04-16 17:51:27 +0000 |
commit | 3201f6beec688ab9fe8750527e28f52d5420e22d (patch) | |
tree | ee806d81273e190e494239c9db4b4b57fafc24e4 /lib/Sema/SemaOverload.cpp | |
parent | ba79fc2d1b742e34df104aadb2780725c2a882fc (diff) |
Fix a crash bug when comparing overload quality of conversion operators with conversion constructors.
Remove an atrocious amount of trailing whitespace in the overloaded operator mangler. Sorry, couldn't help myself.
Change the DeclType parameter of Sema::CheckReferenceInit to be passed by value instead of reference. It wasn't changed anywhere.
Let the parser handle C++'s irregular grammar around assignment-expression and conditional-expression.
And finally, the reason for all this stuff: implement C++ semantics for the conditional operator. The implementation is complete except for determining lvalueness.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69299 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 70c9ee7ef9..6e2e72040e 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2026,15 +2026,19 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, "Use AddConversionCandidate for conversion functions"); if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) { - // If we get here, it's because we're calling a member function - // that is named without a member access expression (e.g., - // "this->f") that was either written explicitly or created - // implicitly. This can happen with a qualified call to a member - // function, e.g., X::f(). We use a NULL object as the implied - // object argument (C++ [over.call.func]p3). - AddMethodCandidate(Method, 0, Args, NumArgs, CandidateSet, - SuppressUserConversions, ForceRValue); - return; + if (!isa<CXXConstructorDecl>(Method)) { + // If we get here, it's because we're calling a member function + // that is named without a member access expression (e.g., + // "this->f") that was either written explicitly or created + // implicitly. This can happen with a qualified call to a member + // function, e.g., X::f(). We use a NULL object as the implied + // object argument (C++ [over.call.func]p3). + AddMethodCandidate(Method, 0, Args, NumArgs, CandidateSet, + SuppressUserConversions, ForceRValue); + return; + } + // We treat a constructor like a non-member function, since its object + // argument doesn't participate in overload resolution. } @@ -2127,8 +2131,10 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, const FunctionProtoType* Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAsFunctionType()); assert(Proto && "Methods without a prototype cannot be overloaded"); - assert(!isa<CXXConversionDecl>(Method) && + assert(!isa<CXXConversionDecl>(Method) && "Use AddConversionCandidate for conversion functions"); + assert(!isa<CXXConstructorDecl>(Method) && + "Use AddOverloadCandidate for constructors"); // Add this candidate CandidateSet.push_back(OverloadCandidate()); @@ -2664,7 +2670,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, Op == OO_Plus || (Op == OO_Minus && NumArgs == 2) || Op == OO_Equal || Op == OO_PlusEqual || Op == OO_MinusEqual || Op == OO_Subscript || Op == OO_ArrowStar || Op == OO_PlusPlus || Op == OO_MinusMinus || - (Op == OO_Star && NumArgs == 1)) { + (Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) { for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(), true, @@ -2939,6 +2945,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_Slash: BinaryStar: + Conditional: // C++ [over.built]p12: // // For every pair of promoted arithmetic types L and R, there @@ -2957,6 +2964,17 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, // // where LR is the result of the usual arithmetic conversions // between types L and R. + // + // C++ [over.built]p24: + // + // For every pair of promoted arithmetic types L and R, there exist + // candidate operator functions of the form + // + // LR operator?(bool, L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // Our candidates ignore the first parameter. for (unsigned Left = FirstPromotedArithmeticType; Left < LastPromotedArithmeticType; ++Left) { for (unsigned Right = FirstPromotedArithmeticType; @@ -3201,6 +3219,25 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_ArrowStar: // FIXME: No support for pointer-to-members yet. break; + + case OO_Conditional: + // Note that we don't consider the first argument, since it has been + // contextually converted to bool long ago. The candidates below are + // therefore added as binary. + // + // C++ [over.built]p24: + // For every type T, where T is a pointer or pointer-to-member type, + // there exist candidate operator functions of the form + // + // T operator?(bool, T, T); + // + // FIXME: pointer-to-member + for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(), + E = CandidateTypes.pointer_end(); Ptr != E; ++Ptr) { + QualType ParamTypes[2] = { *Ptr, *Ptr }; + AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + } + goto Conditional; } } @@ -3852,7 +3889,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Best)) { - case OR_Success: { + case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; |