From: Douglas Gregor Date: Thu, 13 Sep 2012 21:56:43 +0000 (+0000) Subject: When we substitute into the type of a function based on the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71074fdf40a8f5b53810712102b58c27efc30759;p=clang When we substitute into the type of a function based on the TypeSourceInfo, we may have lost some adjustments made to the type of that function due to declaration merging. Adjust the resulting type correspondingly. Fixes PR12948 / . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163845 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 15afd1f6c9..858aabf8a8 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1008,6 +1008,21 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { return Record; } +/// \brief Adjust the given function type for an instantiation of the +/// given declaration, to cope with modifications to the function's type that +/// aren't reflected in the type-source information. +/// +/// \param D The declaration we're instantiating. +/// \param TInfo The already-instantiated type. +static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, + FunctionDecl *D, + TypeSourceInfo *TInfo) { + const FunctionType *OrigFunc = D->getType()->castAs(); + const FunctionType *NewFunc = TInfo->getType()->castAs(); + return QualType(Context.adjustFunctionType(NewFunc, OrigFunc->getExtInfo()), + 0); +} + /// Normal class members are of more specific types and therefore /// don't make it here. This function serves two purposes: /// 1) instantiating function templates @@ -1048,7 +1063,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; - QualType T = TInfo->getType(); + QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { @@ -1366,7 +1381,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; - QualType T = TInfo->getType(); + QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); // \brief If the type of this function, after ignoring parentheses, // is not *directly* a function type, then we're instantiating a function diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp index eaf0d0c15f..f3d548b793 100644 --- a/test/SemaCXX/attr-noreturn.cpp +++ b/test/SemaCXX/attr-noreturn.cpp @@ -54,3 +54,29 @@ class xpto { int xpto::blah() { return 3; // expected-warning {{function 'blah' declared 'noreturn' should not return}} } + +// PR12948 + +namespace PR12948 { + template + void foo() __attribute__((__noreturn__)); + + template + void foo() { + while (1) continue; + } + + void bar() __attribute__((__noreturn__)); + + void bar() { + foo<0>(); + } + + + void baz() __attribute__((__noreturn__)); + typedef void voidfn(); + voidfn baz; + + template void wibble() __attribute__((__noreturn__)); + template voidfn wibble; +}