[c++1z] When initializing a const-qualified class type, don't forget to add on
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 21 Dec 2016 01:31:56 +0000 (01:31 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 21 Dec 2016 01:31:56 +0000 (01:31 +0000)
the requested cv-qualifiers after construction. This usually doesn't matter,
but it does matter within a ?: operator.

llvm-svn: 290227

clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaInit.cpp
clang/test/CXX/expr/expr.cond/p4.cpp [new file with mode: 0644]

index 5c3900a..23e649b 100644 (file)
@@ -5199,8 +5199,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
   //
   // This actually refers very narrowly to the lvalue-to-rvalue conversion, not
   // to the array-to-pointer or function-to-pointer conversions.
-  if (!TTy->getAs<TagType>())
-    TTy = TTy.getUnqualifiedType();
+  TTy = TTy.getNonLValueExprType(Self.Context);
 
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
   InitializationSequence InitSeq(Self, Entity, Kind, From);
index ce01289..515a667 100644 (file)
@@ -3609,17 +3609,7 @@ static void TryConstructorInitialization(Sema &S,
       UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&
       S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
     // Convert qualifications if necessary.
-    QualType InitType = UnwrappedArgs[0]->getType();
-    ImplicitConversionSequence ICS;
-    ICS.setStandard();
-    ICS.Standard.setAsIdentityConversion();
-    ICS.Standard.setFromType(InitType);
-    ICS.Standard.setAllToTypes(InitType);
-    if (!S.Context.hasSameType(InitType, DestType)) {
-      ICS.Standard.Third = ICK_Qualification;
-      ICS.Standard.setToType(2, DestType);
-    }
-    Sequence.AddConversionSequenceStep(ICS, DestType);
+    Sequence.AddQualificationConversionStep(DestType, VK_RValue);
     if (ILE)
       Sequence.RewrapReferenceInitList(DestType, ILE);
     return;
@@ -4790,6 +4780,8 @@ static void TryUserDefinedConversion(Sema &S,
     // FIXME: Mark this copy as extraneous.
     if (!S.getLangOpts().CPlusPlus1z)
       Sequence.AddFinalCopy(DestType);
+    else if (DestType.hasQualifiers())
+      Sequence.AddQualificationConversionStep(DestType, VK_RValue);
     return;
   }
 
@@ -4812,6 +4804,8 @@ static void TryUserDefinedConversion(Sema &S,
         Function->getReturnType()->isReferenceType() ||
         !S.Context.hasSameUnqualifiedType(ConvType, DestType))
       Sequence.AddFinalCopy(DestType);
+    else if (!S.Context.hasSameType(ConvType, DestType))
+      Sequence.AddQualificationConversionStep(DestType, VK_RValue);
     return;
   }
 
diff --git a/clang/test/CXX/expr/expr.cond/p4.cpp b/clang/test/CXX/expr/expr.cond/p4.cpp
new file mode 100644 (file)
index 0000000..4d0cf35
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++98 -verify %s
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+// expected-no-diagnostics
+
+struct A { A(); A(int); };
+void f() {
+  const A a;
+  true ? a : 0;
+}