<div dir="ltr">On Sat, Sep 21, 2013 at 2:55 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Sat Sep 21 16:55:46 2013<br>
New Revision: 191150<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=191150&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=191150&view=rev</a><br>
Log:<br>
PR17295: Do not allow explicit conversion functions to be used in cases where<br>
an additional conversion (other than a qualification conversion) would be<br>
required after the explicit conversion.<br>
<br>
Conversely, do allow explicit conversion functions to be used when initializing<br>
a temporary for a reference binding in direct-list-initialization.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Sema/Initialization.h<br>
    cfe/trunk/lib/Sema/SemaInit.cpp<br>
    cfe/trunk/lib/Sema/SemaOverload.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
    cfe/trunk/test/SemaCXX/explicit.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Initialization.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=191150&r1=191149&r2=191150&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=191150&r1=191149&r2=191150&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Initialization.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Initialization.h Sat Sep 21 16:55:46 2013<br>
@@ -853,6 +853,10 @@ public:<br>
                          const InitializationKind &Kind,<br>
                          MultiExprArg Args,<br>
                          bool InInitList = false);<br>
+  void InitializeFrom(Sema &S, const InitializedEntity &Entity,<br>
+                      const InitializationKind &Kind, MultiExprArg Args,<br>
+                      bool InInitList);<br>
+<br>
   ~InitializationSequence();<br>
<br>
   /// \brief Perform the actual initialization of the given entity based on<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=191150&r1=191149&r2=191150&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=191150&r1=191149&r2=191150&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Sep 21 16:55:46 2013<br>
@@ -3346,6 +3346,33 @@ static void TryListInitialization(Sema &<br>
       return;<br>
     }<br>
   }<br>
+  if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&<br>
+      InitList->getNumInits() == 1 &&<br>
+      InitList->getInit(0)->getType()->isRecordType()) {<br>
+    //   - Otherwise, if the initializer list has a single element of type E<br>
+    //     [...references are handled above...], the object or reference is<br>
+    //     initialized from that element; if a narrowing conversion is required<br>
+    //     to convert the element to T, the program is ill-formed.<br>
+    //<br>
+    // Per core-24034, this is direct-initialization if we were performing<br>
+    // direct-list-initialization and copy-initialization otherwise.<br>
+    // We can't use InitListChecker for this, because it always performs<br>
+    // copy-initialization. This only matters if we might use an 'explicit'<br>
+    // conversion operator, so we only need to handle the cases where the source<br>
+    // is of record type.<br>
+    InitializationKind SubKind =<br>
+        Kind.getKind() == InitializationKind::IK_DirectList<br>
+            ? InitializationKind::CreateDirect(Kind.getLocation(),<br>
+                                               InitList->getLBraceLoc(),<br>
+                                               InitList->getRBraceLoc())<br>
+            : Kind;<br>
+    Expr *SubInit[1] = { InitList->getInit(0) };<br>
+    Sequence.InitializeFrom(S, Entity, SubKind, SubInit,<br>
+                            /*TopLevelOfInitList*/true);<br>
+    if (Sequence)<br>
+      Sequence.RewrapReferenceInitList(Entity.getType(), InitList);<br>
+    return;<br>
+  }<br>
<br>
   InitListChecker CheckInitList(S, Entity, InitList,<br>
           DestType, /*VerifyOnly=*/true);<br>
@@ -4366,6 +4393,14 @@ InitializationSequence::InitializationSe<br>
                                                MultiExprArg Args,<br>
                                                bool TopLevelOfInitList)<br>
     : FailedCandidateSet(Kind.getLocation()) {<br>
+  InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);<br>
+}<br>
+<br>
+void InitializationSequence::InitializeFrom(Sema &S,<br>
+                                            const InitializedEntity &Entity,<br>
+                                            const InitializationKind &Kind,<br>
+                                            MultiExprArg Args,<br>
+                                            bool TopLevelOfInitList) {<br>
   ASTContext &Context = S.Context;<br>
<br>
   // Eliminate non-overload placeholder types in the arguments.  We<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=191150&r1=191149&r2=191150&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=191150&r1=191149&r2=191150&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Sep 21 16:55:46 2013<br>
@@ -5829,6 +5829,17 @@ Sema::AddConversionCandidate(CXXConversi<br>
     ConvType = Conversion->getConversionType().getNonReferenceType();<br>
   }<br>
<br>
+  // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion<br>
+  // operator is only a candidate if its return type is the target type or<br>
+  // can be converted to the target type with a qualification conversion.<br>
+  bool ObjCLifetimeConversion;<br>
+  QualType ToNonRefType = ToType.getNonReferenceType();<br>
+  if (Conversion->isExplicit() &&<br>
+      !Context.hasSameUnqualifiedType(ConvType, ToNonRefType) &&<br>
+      !IsQualificationConversion(ConvType, ToNonRefType, /*CStyle*/false,<br>
+                                 ObjCLifetimeConversion))<br>
+    return;<br>
+<br>
   // Overload resolution is always an unevaluated context.<br>
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=191150&r1=191149&r2=191150&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=191150&r1=191149&r2=191150&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Sep 21 16:55:46 2013<br>
@@ -3372,7 +3372,9 @@ void Sema::BuildVariableInstantiation(<br>
       OldVar->isPreviousDeclInSameBlockScope());<br>
   NewVar->setAccess(OldVar->getAccess());<br>
<br>
-  if (!OldVar->isStaticDataMember()) {<br>
+  // For local variables, inherit the 'used' and 'referenced' flags from the<br>
+  // primary template.<br>
+  if (OldVar->getLexicalDeclContext()->isFunctionOrMethod()) {<br>
     NewVar->setIsUsed(OldVar->isUsed(false));<br>
     NewVar->setReferenced(OldVar->isReferenced());<br>
   }<br></blockquote><div><br>?<br><br></div><div>-Eli<br></div><div><br></div></div></div></div>