]> granicus.if.org Git - clang/commitdiff
When we substitute into the type of a function based on the
authorDouglas Gregor <dgregor@apple.com>
Thu, 13 Sep 2012 21:56:43 +0000 (21:56 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 13 Sep 2012 21:56:43 +0000 (21:56 +0000)
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 / <rdar://problem/11552434>.

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

lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/attr-noreturn.cpp

index 15afd1f6c9950bf2d7bcf458cbfffd5c6f98e062..858aabf8a8b812ff0751bccf950bac21aeb06357 100644 (file)
@@ -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<FunctionType>();
+  const FunctionType *NewFunc = TInfo->getType()->castAs<FunctionType>();
+  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
index eaf0d0c15ffd102c7c8e94dd2db1891074ec6715..f3d548b793b055bc87927555dc06d77516e298a6 100644 (file)
@@ -54,3 +54,29 @@ class xpto {
 int xpto::blah() {
   return 3; // expected-warning {{function 'blah' declared 'noreturn' should not return}}
 }
+
+// PR12948
+
+namespace PR12948 {
+  template<int>
+  void foo() __attribute__((__noreturn__));
+
+  template<int>
+  void foo() {
+    while (1) continue;
+  }
+
+  void bar() __attribute__((__noreturn__));
+
+  void bar() {
+    foo<0>();
+  }
+
+
+  void baz() __attribute__((__noreturn__));
+  typedef void voidfn();
+  voidfn baz;
+
+  template<typename> void wibble()  __attribute__((__noreturn__));
+  template<typename> voidfn wibble;
+}