]> granicus.if.org Git - clang/commitdiff
C++1y deduced return types: when we deduce a return type for a function which
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 May 2013 05:45:24 +0000 (05:45 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 May 2013 05:45:24 +0000 (05:45 +0000)
we loaded from PCH, if we're building another PCH, create an update record to
patch the return type of the earlier declaration.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181659 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTMutationListener.h
include/clang/Serialization/ASTWriter.h
lib/AST/ASTContext.cpp
lib/Frontend/MultiplexConsumer.cpp
lib/Serialization/ASTCommon.h
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/cxx1y-deduced-return-type.cpp [new file with mode: 0644]

index 6b70285e3ad87987a19dde91aac88dfa3956dde4..3681381bf69703140f140b4dc0e64958dda00f9a 100644 (file)
@@ -27,6 +27,7 @@ namespace clang {
   class ObjCContainerDecl;
   class ObjCInterfaceDecl;
   class ObjCPropertyDecl;
+  class QualType;
   class TagDecl;
   class VarDecl;
 
@@ -56,6 +57,9 @@ public:
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D) {}
 
+  /// \brief A function's return type has been deduced.
+  virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
+
   /// \brief An implicit member got a definition.
   virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 
index 8ac8fde88470c1a17e5e94f557fcd3fc9a8803fa..ab8fa079bb4f1e619aef50371daac1d109840696 100644 (file)
@@ -725,6 +725,7 @@ public:
                                     const ClassTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
+  virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
   virtual void CompletedImplicitDefinition(const FunctionDecl *D);
   virtual void StaticDataMemberInstantiated(const VarDecl *D);
   virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
index 960f261816b12bc91ac885144ba4d5acbc7798ce..986bb8c3d2cb8bc339b888272bb0d4763e47b409 100644 (file)
@@ -2057,12 +2057,18 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
 
 void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
                                                  QualType ResultType) {
-  // FIXME: Need to inform serialization code about this!
-  for (FD = FD->getMostRecentDecl(); FD; FD = FD->getPreviousDecl()) {
+  FD = FD->getMostRecentDecl();
+  while (true) {
     const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>();
     FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
     FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI));
+    if (FunctionDecl *Next = FD->getPreviousDecl())
+      FD = Next;
+    else
+      break;
   }
+  if (ASTMutationListener *L = getASTMutationListener())
+    L->DeducedReturnType(FD, ResultType);
 }
 
 /// getComplexType - Return the uniqued reference to the type for a complex
@@ -7458,6 +7464,8 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
 
 ASTMutationListener::~ASTMutationListener() { }
 
+void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
+                                            QualType ReturnType) {}
 
 //===----------------------------------------------------------------------===//
 //                          Builtin Type Computation
index ba83580cb69c980240f7b72f62401237b097269e..7ed9d36ca3b468c6c2be20bf2f332addb0de0720 100644 (file)
@@ -96,6 +96,7 @@ public:
                                     const ClassTemplateSpecializationDecl *D);
   virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D);
+  virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
   virtual void CompletedImplicitDefinition(const FunctionDecl *D);
   virtual void StaticDataMemberInstantiated(const VarDecl *D);
   virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
@@ -138,6 +139,11 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
 }
+void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
+                                                     QualType ReturnType) {
+  for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+    Listeners[i]->DeducedReturnType(FD, ReturnType);
+}
 void MultiplexASTMutationListener::CompletedImplicitDefinition(
                                                         const FunctionDecl *D) {
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
index 76ef9040461c08329221753316076a526924f90a..fa3ef58a1c0808ce865811721258b9fd27e3b794 100644 (file)
@@ -25,7 +25,8 @@ enum DeclUpdateKind {
   UPD_CXX_ADDED_IMPLICIT_MEMBER,
   UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
   UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
-  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER
+  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+  UPD_CXX_DEDUCED_RETURN_TYPE
 };
 
 TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
index f7fa818e9b3a69c064e77008d6cce5c984c89a8f..086acd261d3d902cb4fb85662cad09df780b2287 100644 (file)
@@ -2582,6 +2582,13 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
       cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
           Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       break;
+
+    case UPD_CXX_DEDUCED_RETURN_TYPE: {
+      FunctionDecl *FD = cast<FunctionDecl>(D);
+      Reader.Context.adjustDeducedFunctionResultType(
+          FD, Reader.readType(ModuleFile, Record, Idx));
+      break;
+    }
     }
   }
 }
index a96ecd7b86c25547a43c8de8f23d51fb01ab01df..dd5818f843df77aa06c5e4c95734160ec67b2c5c 100644 (file)
@@ -4230,10 +4230,16 @@ void ASTWriter::ResolveDeclUpdatesBlocks() {
         URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
         ++Idx;
         break;
-          
+
       case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
         ++Idx;
         break;
+
+      case UPD_CXX_DEDUCED_RETURN_TYPE:
+        URec[Idx] = GetOrCreateTypeID(
+            QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx])));
+        ++Idx;
+        break;
       }
     }
   }
@@ -4448,11 +4454,13 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) {
 }
 
 TypeID ASTWriter::GetOrCreateTypeID( QualType T) {
+  assert(Context);
   return MakeTypeID(*Context, T,
               std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
 }
 
 TypeID ASTWriter::getTypeID(QualType T) const {
+  assert(Context);
   return MakeTypeID(*Context, T,
               std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
 }
@@ -5189,6 +5197,17 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
   Record.push_back(reinterpret_cast<uint64_t>(D));
 }
 
+void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
+  assert(!WritingAST && "Already writing the AST!");
+  FD = FD->getCanonicalDecl();
+  if (!FD->isFromASTFile())
+    return; // Not a function declared in PCH and defined outside.
+
+  UpdateRecord &Record = DeclUpdates[FD];
+  Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE);
+  Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr()));
+}
+
 void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
   assert(!WritingAST && "Already writing the AST!");
   if (!D->isFromASTFile())
diff --git a/test/PCH/cxx1y-deduced-return-type.cpp b/test/PCH/cxx1y-deduced-return-type.cpp
new file mode 100644 (file)
index 0000000..a61dda2
--- /dev/null
@@ -0,0 +1,34 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s
+//
+// With chained PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t.a
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s
+
+// expected-no-diagnostics
+
+#if !defined(HEADER1)
+#define HEADER1
+
+auto &f(int &);
+
+template<typename T> decltype(auto) g(T &t) {
+  return f(t);
+}
+
+#elif !defined(HEADER2)
+#define HEADER2
+
+// Ensure that this provides an update record for the type of HEADER1's 'f',
+// so that HEADER1's 'g' can successfully call it.
+auto &f(int &n) {
+  return n;
+}
+
+#else
+
+int n;
+int &k = g(n);
+
+#endif