On 10 June 2013 02:50, Larisse Voufo <[email protected]> wrote: > Author: lvoufo > Date: Mon Jun 10 01:50:24 2013 > New Revision: 183637 > > URL: http://llvm.org/viewvc/llvm-project?rev=183637&view=rev > Log: > reverted test
There is a lot more in here than in 183636. Was this an accidental commit? > > Added: > cfe/trunk/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp > Modified: > cfe/trunk/lib/Sema/SemaOverload.cpp > cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=183637&r1=183636&r2=183637&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jun 10 01:50:24 2013 > @@ -5121,6 +5121,130 @@ bool Sema::ICEConvertDiagnoser::match(Qu > : T->isIntegralOrUnscopedEnumerationType(); > } > > +static ExprResult > +diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From, > + Sema::ContextualImplicitConverter &Converter, > + QualType T, UnresolvedSetImpl > &ViableConversions) { > + > + if (Converter.Suppress) > + return ExprError(); > + > + Converter.diagnoseAmbiguous(SemaRef, Loc, T) << From->getSourceRange(); > + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { > + CXXConversionDecl *Conv = > + cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); > + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); > + Converter.noteAmbiguous(SemaRef, Conv, ConvTy); > + } > + return SemaRef.Owned(From); > +} > + > +static bool > +diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, > + Sema::ContextualImplicitConverter &Converter, > + QualType T, bool HadMultipleCandidates, > + UnresolvedSetImpl &ExplicitConversions) { > + if (ExplicitConversions.size() == 1 && !Converter.Suppress) { > + DeclAccessPair Found = ExplicitConversions[0]; > + CXXConversionDecl *Conversion = > + cast<CXXConversionDecl>(Found->getUnderlyingDecl()); > + > + // The user probably meant to invoke the given explicit > + // conversion; use it. > + QualType ConvTy = Conversion->getConversionType().getNonReferenceType(); > + std::string TypeStr; > + ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy()); > + > + Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy) > + << FixItHint::CreateInsertion(From->getLocStart(), > + "static_cast<" + TypeStr + ">(") > + << FixItHint::CreateInsertion( > + SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")"); > + Converter.noteExplicitConv(SemaRef, Conversion, ConvTy); > + > + // If we aren't in a SFINAE context, build a call to the > + // explicit conversion function. > + if (SemaRef.isSFINAEContext()) > + return true; > + > + SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); > + ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, > Conversion, > + > HadMultipleCandidates); > + if (Result.isInvalid()) > + return true; > + // Record usage of conversion in an implicit cast. > + From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), > + CK_UserDefinedConversion, Result.get(), > 0, > + Result.get()->getValueKind()); > + } > + return false; > +} > + > +static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, > + Sema::ContextualImplicitConverter &Converter, > + QualType T, bool HadMultipleCandidates, > + DeclAccessPair &Found) { > + CXXConversionDecl *Conversion = > + cast<CXXConversionDecl>(Found->getUnderlyingDecl()); > + SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); > + > + QualType ToType = Conversion->getConversionType().getNonReferenceType(); > + if (!Converter.SuppressConversion) { > + if (SemaRef.isSFINAEContext()) > + return true; > + > + Converter.diagnoseConversion(SemaRef, Loc, T, ToType) > + << From->getSourceRange(); > + } > + > + ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion, > + HadMultipleCandidates); > + if (Result.isInvalid()) > + return true; > + // Record usage of conversion in an implicit cast. > + From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), > + CK_UserDefinedConversion, Result.get(), 0, > + Result.get()->getValueKind()); > + return false; > +} > + > +static ExprResult finishContextualImplicitConversion( > + Sema &SemaRef, SourceLocation Loc, Expr *From, > + Sema::ContextualImplicitConverter &Converter) { > + if (!Converter.match(From->getType()) && !Converter.Suppress) > + Converter.diagnoseNoMatch(SemaRef, Loc, From->getType()) > + << From->getSourceRange(); > + > + return SemaRef.DefaultLvalueConversion(From); > +} > + > +static void > +collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, > + UnresolvedSetImpl &ViableConversions, > + OverloadCandidateSet &CandidateSet) { > + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { > + DeclAccessPair FoundDecl = ViableConversions[I]; > + NamedDecl *D = FoundDecl.getDecl(); > + CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); > + if (isa<UsingShadowDecl>(D)) > + D = cast<UsingShadowDecl>(D)->getTargetDecl(); > + > + CXXConversionDecl *Conv; > + FunctionTemplateDecl *ConvTemplate; > + if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D))) > + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); > + else > + Conv = cast<CXXConversionDecl>(D); > + > + if (ConvTemplate) > + SemaRef.AddTemplateConversionCandidate( > + ConvTemplate, FoundDecl, ActingContext, From, ToType, > CandidateSet); > + else > + SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, > + ToType, CandidateSet); > + } > +} > + > /// \brief Attempt to convert the given expression to a type which is > accepted > /// by the given converter. > /// > @@ -5148,7 +5272,8 @@ ExprResult Sema::PerformContextualImplic > // Process placeholders immediately. > if (From->hasPlaceholderType()) { > ExprResult result = CheckPlaceholderExpr(From); > - if (result.isInvalid()) return result; > + if (result.isInvalid()) > + return result; > From = result.take(); > } > > @@ -5185,119 +5310,142 @@ ExprResult Sema::PerformContextualImplic > return Owned(From); > > // Look for a conversion to an integral or enumeration type. > - UnresolvedSet<4> ViableConversions; > + UnresolvedSet<4> > + ViableConversions; // These are *potentially* viable in C++1y. > UnresolvedSet<4> ExplicitConversions; > std::pair<CXXRecordDecl::conversion_iterator, > - CXXRecordDecl::conversion_iterator> Conversions > - = > cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); > + CXXRecordDecl::conversion_iterator> Conversions = > + > cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); > > - bool HadMultipleCandidates > - = (std::distance(Conversions.first, Conversions.second) > 1); > + bool HadMultipleCandidates = > + (std::distance(Conversions.first, Conversions.second) > 1); > > - for (CXXRecordDecl::conversion_iterator > - I = Conversions.first, E = Conversions.second; I != E; ++I) { > - if (CXXConversionDecl *Conversion > - = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { > - if (Converter.match( > - Conversion->getConversionType().getNonReferenceType())) { > - if (Conversion->isExplicit()) > + // To check that there is only one target type, in C++1y: > + QualType ToType; > + bool HasUniqueTargetType = true; > + > + // Collect explicit or viable (potentially in C++1y) conversions. > + for (CXXRecordDecl::conversion_iterator I = Conversions.first, > + E = Conversions.second; > + I != E; ++I) { > + NamedDecl *D = (*I)->getUnderlyingDecl(); > + CXXConversionDecl *Conversion; > + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D); > + if (ConvTemplate) { > + if (getLangOpts().CPlusPlus1y) > + Conversion = > cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); > + else > + continue; // C++11 does not consider conversion operator > templates(?). > + } else > + Conversion = cast<CXXConversionDecl>(D); > + > + assert((!ConvTemplate || getLangOpts().CPlusPlus1y) && > + "Conversion operator templates are considered potentially " > + "viable in C++1y"); > + > + QualType CurToType = > Conversion->getConversionType().getNonReferenceType(); > + if (Converter.match(CurToType) || ConvTemplate) { > + > + if (Conversion->isExplicit()) { > + // FIXME: For C++1y, do we need this restriction? > + // cf. diagnoseNoViableConversion() > + if (!ConvTemplate) > ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); > - else > - ViableConversions.addDecl(I.getDecl(), I.getAccess()); > + } else { > + if (!ConvTemplate && getLangOpts().CPlusPlus1y) { > + if (ToType.isNull()) > + ToType = CurToType.getUnqualifiedType(); > + else if (HasUniqueTargetType && > + (CurToType.getUnqualifiedType() != ToType)) > + HasUniqueTargetType = false; > + } > + ViableConversions.addDecl(I.getDecl(), I.getAccess()); > } > } > } > > - // FIXME: Implement the C++11 rules! > - switch (ViableConversions.size()) { > - case 0: > - if (ExplicitConversions.size() == 1 && !Converter.Suppress) { > - DeclAccessPair Found = ExplicitConversions[0]; > - CXXConversionDecl *Conversion > - = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); > - > - // The user probably meant to invoke the given explicit > - // conversion; use it. > - QualType ConvTy > - = Conversion->getConversionType().getNonReferenceType(); > - std::string TypeStr; > - ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy()); > - > - Converter.diagnoseExplicitConv(*this, Loc, T, ConvTy) > - << FixItHint::CreateInsertion(From->getLocStart(), > - "static_cast<" + TypeStr + ">(") > - << > FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), > - ")"); > - Converter.noteExplicitConv(*this, Conversion, ConvTy); > - > - // If we aren't in a SFINAE context, build a call to the > - // explicit conversion function. > - if (isSFINAEContext()) > + if (getLangOpts().CPlusPlus1y) { > + // C++1y [conv]p6: > + // ... An expression e of class type E appearing in such a context > + // is said to be contextually implicitly converted to a specified > + // type T and is well-formed if and only if e can be implicitly > + // converted to a type T that is determined as follows: E is searched > + // for conversion functions whose return type is cv T or reference > + // to cv T such that T is allowed by the context. There shall be > + // exactly one such T. > + > + // If no unique T is found: > + if (ToType.isNull()) { > + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, > + HadMultipleCandidates, > + ExplicitConversions)) > return ExprError(); > + return finishContextualImplicitConversion(*this, Loc, From, Converter); > + } > > - CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); > - ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, > - HadMultipleCandidates); > - if (Result.isInvalid()) > + // If more than one unique Ts are found: > + if (!HasUniqueTargetType) > + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, > + ViableConversions); > + > + // If one unique T is found: > + // First, build a candidate set from the previously recorded > + // potentially viable conversions. > + OverloadCandidateSet CandidateSet(Loc); > + collectViableConversionCandidates(*this, From, ToType, ViableConversions, > + CandidateSet); > + > + // Then, perform overload resolution over the candidate set. > + OverloadCandidateSet::iterator Best; > + switch (CandidateSet.BestViableFunction(*this, Loc, Best)) { > + case OR_Success: { > + // Apply this conversion. > + DeclAccessPair Found = > + DeclAccessPair::make(Best->Function, Best->FoundDecl.getAccess()); > + if (recordConversion(*this, Loc, From, Converter, T, > + HadMultipleCandidates, Found)) > return ExprError(); > - // Record usage of conversion in an implicit cast. > - From = ImplicitCastExpr::Create(Context, Result.get()->getType(), > - CK_UserDefinedConversion, > - Result.get(), 0, > - Result.get()->getValueKind()); > - } > - > - // We'll complain below about a non-integral condition type. > - break; > - > - case 1: { > - // Apply this conversion. > - DeclAccessPair Found = ViableConversions[0]; > - CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); > - > - CXXConversionDecl *Conversion > - = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); > - QualType ConvTy > - = Conversion->getConversionType().getNonReferenceType(); > - if (!Converter.SuppressConversion) { > - if (isSFINAEContext()) > + break; > + } > + case OR_Ambiguous: > + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, > + ViableConversions); > + case OR_No_Viable_Function: > + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, > + HadMultipleCandidates, > + ExplicitConversions)) > return ExprError(); > - > - Converter.diagnoseConversion(*this, Loc, T, ConvTy) > - << From->getSourceRange(); > + // fall through 'OR_Deleted' case. > + case OR_Deleted: > + // We'll complain below about a non-integral condition type. > + break; > } > + } else { > + switch (ViableConversions.size()) { > + case 0: { > + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, > + HadMultipleCandidates, > + ExplicitConversions)) > + return ExprError(); > > - ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, > - HadMultipleCandidates); > - if (Result.isInvalid()) > - return ExprError(); > - // Record usage of conversion in an implicit cast. > - From = ImplicitCastExpr::Create(Context, Result.get()->getType(), > - CK_UserDefinedConversion, > - Result.get(), 0, > - Result.get()->getValueKind()); > - break; > - } > - > - default: > - if (Converter.Suppress) > - return ExprError(); > - > - Converter.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange(); > - for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { > - CXXConversionDecl *Conv > - = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); > - QualType ConvTy = Conv->getConversionType().getNonReferenceType(); > - Converter.noteAmbiguous(*this, Conv, ConvTy); > + // We'll complain below about a non-integral condition type. > + break; > + } > + case 1: { > + // Apply this conversion. > + DeclAccessPair Found = ViableConversions[0]; > + if (recordConversion(*this, Loc, From, Converter, T, > + HadMultipleCandidates, Found)) > + return ExprError(); > + break; > + } > + default: > + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, > + ViableConversions); > } > - return Owned(From); > } > > - if (!Converter.match(From->getType()) && !Converter.Suppress) > - Converter.diagnoseNoMatch(*this, Loc, From->getType()) > - << From->getSourceRange(); > - > - return DefaultLvalueConversion(From); > + return finishContextualImplicitConversion(*this, Loc, From, Converter); > } > > /// AddOverloadCandidate - Adds the given function to the set of > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=183637&r1=183636&r2=183637&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Jun 10 01:50:24 > 2013 > @@ -2842,7 +2842,6 @@ void Sema::InstantiateFunctionDefinition > if (Function->isInvalidDecl() || Function->isDefined()) > return; > > - > // Never instantiate an explicit specialization except if it is a class > scope > // explicit specialization. > if (Function->getTemplateSpecializationKind() == > TSK_ExplicitSpecialization && > > Added: cfe/trunk/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp?rev=183637&view=auto > ============================================================================== > --- cfe/trunk/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp (added) > +++ cfe/trunk/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp Mon Jun 10 > 01:50:24 2013 > @@ -0,0 +1,157 @@ > +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s > +// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y > + > +// Explicit member declarations behave as in C++11. > + > +namespace n3323_example { > + > + template <class T> class zero_init { > + public: > + zero_init() : val(static_cast<T>(0)) {} > + zero_init(T val) : val(val) {} > + > + operator T &() { return val; } //@13 > + operator T() const { return val; } //@14 > + > + private: > + T val; > + }; > + > + void Delete() { > + zero_init<int *> p; > + p = new int(7); > + delete p; //@23 > + delete (p + 0); > + delete + p; > + } > + > + void Switch() { > + zero_init<int> i; > + i = 7; > + switch (i) {} // @31 > + switch (i + 0) {} > + switch (+i) {} > + } > +} > + > +#ifdef CXX1Y > +#else > +//expected-error@23 {{ambiguous conversion of delete expression of type > 'zero_init<int *>' to a pointer}} > +//expected-note@13 {{conversion to pointer type 'int *'}} > +//expected-note@14 {{conversion to pointer type 'int *'}} > +//expected-error@31 {{multiple conversions from switch condition type > 'zero_init<int>' to an integral or enumeration type}} > +//expected-note@13 {{conversion to integral type 'int'}} > +//expected-note@14 {{conversion to integral type 'int'}} > +#endif > + > +namespace extended_examples { > + > + struct A0 { > + operator int(); // matching and viable > + }; > + > + struct A1 { > + operator int() &&; // matching and not viable > + }; > + > + struct A2 { > + operator float(); // not matching > + }; > + > + struct A3 { > + template<typename T> operator T(); // not matching (ambiguous anyway) > + }; > + > + struct A4 { > + template<typename T> operator int(); // not matching (ambiguous anyway) > + }; > + > + struct B1 { > + operator int() &&; // @70 > + operator int(); // @71 -- duplicate declaration with different > qualifier is not allowed > + }; > + > + struct B2 { > + operator int() &&; // matching but not viable > + operator float(); // not matching > + }; > + > + void foo(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, B2 b2) { > + switch (a0) {} > + switch (a1) {} // @81 -- fails for different reasons > + switch (a2) {} // @82 > + switch (a3) {} // @83 > + switch (a4) {} // @84 > + switch (b2) {} // @85 -- fails for different reasons > + } > +} > + > +//expected-error@71 {{cannot overload a member function without a > ref-qualifier with a member function with ref-qualifier '&&'}} > +//expected-note@70 {{previous declaration is here}} > +//expected-error@82 {{statement requires expression of integer type > ('extended_examples::A2' invalid)}} > +//expected-error@83 {{statement requires expression of integer type > ('extended_examples::A3' invalid)}} > +//expected-error@84 {{statement requires expression of integer type > ('extended_examples::A4' invalid)}} > + > +#ifdef CXX1Y > +//expected-error@81 {{statement requires expression of integer type > ('extended_examples::A1' invalid)}} > +//expected-error@85 {{statement requires expression of integer type > ('extended_examples::B2' invalid)}} > +#else > +//expected-error@81 {{cannot initialize object parameter of type > 'extended_examples::A1' with an expression of type 'extended_examples::A1'}} > +//expected-error@85 {{cannot initialize object parameter of type > 'extended_examples::B2' with an expression of type 'extended_examples::B2'}} > +#endif > + > +namespace extended_examples_cxx1y { > + > + struct A1 { // leads to viable match in C++1y, and no viable match in > C++11 > + operator int() &&; // matching but not viable > + template <typename T> operator T(); // In C++1y: matching and viable, > since disambiguated by L.100 > + }; > + > + struct A2 { // leads to ambiguity in C++1y, and no viable match in C++11 > + operator int() &&; // matching but not viable > + template <typename T> operator int(); // In C++1y: matching but > ambiguous (disambiguated by L.105). > + }; > + > + struct B1 { // leads to one viable match in both cases > + operator int(); // matching and viable > + template <typename T> operator T(); // In C++1y: matching and viable, > since disambiguated by L.110 > + }; > + > + struct B2 { // leads to one viable match in both cases > + operator int(); // matching and viable > + template <typename T> operator int(); // In C++1y: matching but > ambiguous, since disambiguated by L.115 > + }; > + > + struct C { // leads to no match in both cases > + operator float(); // not matching > + template <typename T> operator T(); // In C++1y: not matching, nor > viable. > + }; > + > + struct D { // leads to viable match in C++1y, and no viable match in > C++11 > + operator int() &&; // matching but not viable > + operator float(); // not matching > + template <typename T> operator T(); // In C++1y: matching and viable, > since disambiguated by L.125 > + }; > + > + > + void foo(A1 a1, A2 a2, B1 b1, B2 b2, C c, D d) { > + switch (a1) {} // @138 -- should presumably call templated conversion > operator to convert to int. > + switch (a2) {} // @139 > + switch (b1) {} > + switch (b2) {} > + switch (c) {} // @142 > + switch (d) {} // @143 > + } > +} > + > +//expected-error@142 {{statement requires expression of integer type > ('extended_examples_cxx1y::C' invalid)}} > + > +#ifdef CXX1Y > +//expected-error@139 {{statement requires expression of integer type > ('extended_examples_cxx1y::A2' invalid)}} > +#else > +//expected-error@138 {{cannot initialize object parameter of type > 'extended_examples_cxx1y::A1' with an expression of type > 'extended_examples_cxx1y::A1'}} > +//expected-error@139 {{cannot initialize object parameter of type > 'extended_examples_cxx1y::A2' with an expression of type > 'extended_examples_cxx1y::A2'}} > +//expected-error@143 {{cannot initialize object parameter of type > 'extended_examples_cxx1y::D' with an expression of type > 'extended_examples_cxx1y::D'}} > +#endif > + > +// FIXME: Extend with more examples, including [expr.const] and [expr.new]. > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
