[llvm-branch-commits] [cfe-branch] r345412 - Merging r341778:

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 26 10:59:43 PDT 2018


Author: tstellar
Date: Fri Oct 26 10:59:43 2018
New Revision: 345412

URL: http://llvm.org/viewvc/llvm-project?rev=345412&view=rev
Log:
Merging r341778:

------------------------------------------------------------------------
r341778 | rsmith | 2018-09-09 23:35:32 -0700 (Sun, 09 Sep 2018) | 5 lines

PR33222: Require the declared return type not the actual return type to
match when checking for redeclaration of a function template.

This properly handles differences in deduced return types, particularly
when performing redeclaration checks for a friend function template.
------------------------------------------------------------------------

Modified:
    cfe/branches/release_70/include/clang/AST/Decl.h
    cfe/branches/release_70/lib/Sema/SemaDecl.cpp
    cfe/branches/release_70/lib/Sema/SemaOverload.cpp
    cfe/branches/release_70/lib/Sema/SemaTemplate.cpp
    cfe/branches/release_70/test/SemaCXX/cxx1y-deduced-return-type.cpp

Modified: cfe/branches/release_70/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_70/include/clang/AST/Decl.h?rev=345412&r1=345411&r2=345412&view=diff
==============================================================================
--- cfe/branches/release_70/include/clang/AST/Decl.h (original)
+++ cfe/branches/release_70/include/clang/AST/Decl.h Fri Oct 26 10:59:43 2018
@@ -2269,8 +2269,7 @@ public:
   unsigned getMinRequiredArguments() const;
 
   QualType getReturnType() const {
-    assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
-    return getType()->getAs<FunctionType>()->getReturnType();
+    return getType()->castAs<FunctionType>()->getReturnType();
   }
 
   /// Attempt to compute an informative source range covering the
@@ -2278,14 +2277,22 @@ public:
   /// limited representation in the AST.
   SourceRange getReturnTypeSourceRange() const;
 
+  /// Get the declared return type, which may differ from the actual return
+  /// type if the return type is deduced.
+  QualType getDeclaredReturnType() const {
+    auto *TSI = getTypeSourceInfo();
+    QualType T = TSI ? TSI->getType() : getType();
+    return T->castAs<FunctionType>()->getReturnType();
+  }
+
   /// Attempt to compute an informative source range covering the
   /// function exception specification, if any.
   SourceRange getExceptionSpecSourceRange() const;
 
   /// Determine the type of an expression that calls this function.
   QualType getCallResultType() const {
-    assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
-    return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
+    return getType()->castAs<FunctionType>()->getCallResultType(
+        getASTContext());
   }
 
   /// Returns the WarnUnusedResultAttr that is either declared on this

Modified: cfe/branches/release_70/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_70/lib/Sema/SemaDecl.cpp?rev=345412&r1=345411&r2=345412&view=diff
==============================================================================
--- cfe/branches/release_70/lib/Sema/SemaDecl.cpp (original)
+++ cfe/branches/release_70/lib/Sema/SemaDecl.cpp Fri Oct 26 10:59:43 2018
@@ -3249,20 +3249,15 @@ bool Sema::MergeFunctionDecl(FunctionDec
     //   Redeclarations or specializations of a function or function template
     //   with a declared return type that uses a placeholder type shall also
     //   use that placeholder, not a deduced type.
-    QualType OldDeclaredReturnType =
-        (Old->getTypeSourceInfo()
-             ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
-             : OldType)->getReturnType();
-    QualType NewDeclaredReturnType =
-        (New->getTypeSourceInfo()
-             ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
-             : NewType)->getReturnType();
+    QualType OldDeclaredReturnType = Old->getDeclaredReturnType();
+    QualType NewDeclaredReturnType = New->getDeclaredReturnType();
     if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
         canFullyTypeCheckRedeclaration(New, Old, NewDeclaredReturnType,
                                        OldDeclaredReturnType)) {
       QualType ResQT;
       if (NewDeclaredReturnType->isObjCObjectPointerType() &&
           OldDeclaredReturnType->isObjCObjectPointerType())
+        // FIXME: This does the wrong thing for a deduced return type.
         ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
       if (ResQT.isNull()) {
         if (New->isCXXClassMember() && New->isOutOfLine())

Modified: cfe/branches/release_70/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_70/lib/Sema/SemaOverload.cpp?rev=345412&r1=345411&r2=345412&view=diff
==============================================================================
--- cfe/branches/release_70/lib/Sema/SemaOverload.cpp (original)
+++ cfe/branches/release_70/lib/Sema/SemaOverload.cpp Fri Oct 26 10:59:43 2018
@@ -1105,7 +1105,8 @@ bool Sema::IsOverload(FunctionDecl *New,
       (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
                                        OldTemplate->getTemplateParameters(),
                                        false, TPL_TemplateMatch) ||
-       OldType->getReturnType() != NewType->getReturnType()))
+       !Context.hasSameType(Old->getDeclaredReturnType(),
+                            New->getDeclaredReturnType())))
     return true;
 
   // If the function is a class member, its signature includes the

Modified: cfe/branches/release_70/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_70/lib/Sema/SemaTemplate.cpp?rev=345412&r1=345411&r2=345412&view=diff
==============================================================================
--- cfe/branches/release_70/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/branches/release_70/lib/Sema/SemaTemplate.cpp Fri Oct 26 10:59:43 2018
@@ -8304,6 +8304,8 @@ Sema::CheckMemberSpecialization(NamedDec
         QualType Adjusted = Function->getType();
         if (!hasExplicitCallingConv(Adjusted))
           Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+        // This doesn't handle deduced return types, but both function
+        // declarations should be undeduced at this point.
         if (Context.hasSameType(Adjusted, Method->getType())) {
           FoundInstantiation = *I;
           Instantiation = Method;

Modified: cfe/branches/release_70/test/SemaCXX/cxx1y-deduced-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_70/test/SemaCXX/cxx1y-deduced-return-type.cpp?rev=345412&r1=345411&r2=345412&view=diff
==============================================================================
--- cfe/branches/release_70/test/SemaCXX/cxx1y-deduced-return-type.cpp (original)
+++ cfe/branches/release_70/test/SemaCXX/cxx1y-deduced-return-type.cpp Fri Oct 26 10:59:43 2018
@@ -552,3 +552,73 @@ namespace PR24989 {
 void forinit_decltypeauto() {
   for (decltype(auto) forinit_decltypeauto_inner();;) {} // expected-warning {{interpreted as a function}} expected-note {{replace}}
 }
+
+namespace PR33222 {
+  auto f1();
+  auto f2();
+
+  template<typename T> decltype(auto) g0(T x) { return x.n; }
+  template<typename T> decltype(auto) g1(T);
+  template<typename T> decltype(auto) g2(T);
+
+  struct X {
+    static auto f1();
+    static auto f2();
+
+    template<typename T> static decltype(auto) g0(T x) { return x.n; } // FIXME (PR38883): expected-error {{private}}
+    template<typename T> static decltype(auto) g1(T);
+    template<typename T> static decltype(auto) g2(T);
+  };
+
+  template<typename U> class A {
+    friend auto f1();
+    friend auto f2();
+
+    // FIXME (PR38883): This friend declaration doesn't actually work, because
+    // we fail to look up the named function properly during instantiation.
+    friend decltype(auto) g0<>(A);
+    template<typename T> friend decltype(auto) g1(T);
+    template<typename T> friend decltype(auto) g2(T);
+
+    friend auto X::f1();
+    friend auto X::f2();
+
+    // FIXME (PR38882): 'A' names the class template not the injected-class-name here!
+    friend decltype(auto) X::g0<>(A<U>);
+    // FIXME (PR38882): ::T hides the template parameter if both are named T here!
+    template<typename T_> friend decltype(auto) X::g1(T_);
+    template<typename T_> friend decltype(auto) X::g2(T_);
+
+    int n; // FIXME: expected-note {{here}}
+  };
+
+  auto f1() { return A<int>().n; }
+  template<typename T> decltype(auto) g1(T x) { return A<int>().n; }
+
+  auto X::f1() { return A<int>().n; }
+  template<typename T> decltype(auto) X::g1(T x) { return A<int>().n; }
+
+  A<int> ai;
+  int k1 = g0(ai);
+  int k2 = X::g0(ai); // FIXME: expected-note {{in instantiation of}}
+
+  int k3 = g1(ai);
+  int k4 = X::g1(ai);
+
+  auto f2() { return A<int>().n; }
+  template<typename T> decltype(auto) g2(T x) { return A<int>().n; }
+
+  auto X::f2() { return A<int>().n; }
+  template<typename T> decltype(auto) X::g2(T x) { return A<int>().n; }
+
+  int k5 = g2(ai);
+  int k6 = X::g2(ai);
+
+  template<typename> struct B {
+    auto *q() { return (float*)0; } // expected-note 2{{previous}}
+  };
+  template<> auto *B<char[1]>::q() { return (int*)0; }
+  template<> auto B<char[2]>::q() { return (int*)0; } // expected-error {{return type}}
+  // FIXME: suppress this follow-on error: expected-error at -1 {{cannot initialize}}
+  template<> int B<char[3]>::q() { return 0; } // expected-error {{return type}}
+}




More information about the llvm-branch-commits mailing list