From: Richard Smith Date: Sat, 11 May 2013 05:45:24 +0000 (+0000) Subject: C++1y deduced return types: when we deduce a return type for a function which X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9dadfab2faebe40e7dbbfd0801c15174b69bd726;p=clang C++1y deduced return types: when we deduce a return type for a function which 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 --- diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 6b70285e3a..3681381bf6 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -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) {} diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 8ac8fde884..ab8fa079bb 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -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, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 960f261816..986bb8c3d2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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::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 diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index ba83580cb6..7ed9d36ca3 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -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) diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index 76ef904046..fa3ef58a1c 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -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); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index f7fa818e9b..086acd261d 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2582,6 +2582,13 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, cast(D)->getMemberSpecializationInfo()->setPointOfInstantiation( Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; + + case UPD_CXX_DEDUCED_RETURN_TYPE: { + FunctionDecl *FD = cast(D); + Reader.Context.adjustDeducedFunctionResultType( + FD, Reader.readType(ModuleFile, Record, Idx)); + break; + } } } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index a96ecd7b86..dd5818f843 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4230,10 +4230,16 @@ void ASTWriter::ResolveDeclUpdatesBlocks() { URec[Idx] = GetDeclRef(reinterpret_cast(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(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(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(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 index 0000000000..a61dda21e7 --- /dev/null +++ b/test/PCH/cxx1y-deduced-return-type.cpp @@ -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 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