Use a FunctionProtoType::ExtProtoInfo in Sema::BuildFunctionType if one is 
available.

  I'm not sure we actually need to keep the old overload of BuildFunctionType 
around; there aren't any callers anymore. What do you think? Should we just 
require ExtProtoInfo all the time?

  Also, drop attributes in StripImplicitInstantiation (though since 
`ns_consumed` and friends are type-sensitive, it will refuse an explicit 
specialization without them anyway).

  This patch depends on ArrayRef-ization of Sema::BuildFunctionType and 
ASTContext::getFunctionType, which I'm about to commit once it passes all the 
tests.

Hi doug.gregor, rsmith,

http://llvm-reviews.chandlerc.com/D474

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D474?vs=1135&id=1219#toc

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaTemplate.cpp
  lib/Sema/SemaTemplateDeduction.cpp
  lib/Sema/SemaTemplateInstantiate.cpp
  lib/Sema/SemaType.cpp
  lib/Sema/TreeTransform.h
  test/CodeGenObjCXX/arc-attrs.mm
  test/SemaObjCXX/arc-nsconsumed-errors.mm
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -981,6 +981,15 @@
                              SourceLocation Loc, DeclarationName Entity,
                              FunctionType::ExtInfo Info);
 
+  /// \brief Build a function type with a prototype.
+  ///
+  /// Use this instead of the other BuildFunctionType overload when you have
+  /// an ExtProtoInfo available.
+  QualType BuildFunctionType(QualType T,
+                             llvm::MutableArrayRef<QualType> ParamTypes,
+                             SourceLocation Loc, DeclarationName Entity,
+                             FunctionProtoType::ExtProtoInfo EPI);
+
   QualType BuildMemberPointerType(QualType T, QualType Class,
                                   SourceLocation Loc,
                                   DeclarationName Entity);
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -5648,11 +5648,15 @@
 /// \brief Strips various properties off an implicit instantiation
 /// that has just been explicitly specialized.
 static void StripImplicitInstantiation(NamedDecl *D) {
-  // FIXME: "make check" is clean if the call to dropAttrs() is commented out.
   D->dropAttrs();
 
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     FD->setInlineSpecified(false);
+
+    for (FunctionDecl::param_iterator I = FD->param_begin(),
+                                      E = FD->param_end();
+         I != E; ++I)
+      (*I)->dropAttrs();
   }
 }
 
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -2418,13 +2418,9 @@
 
   if (FunctionType) {
     *FunctionType = BuildFunctionType(ResultType, ParamTypes,
-                                      Proto->isVariadic(),
-                                      Proto->hasTrailingReturn(),
-                                      Proto->getTypeQuals(),
-                                      Proto->getRefQualifier(),
                                       Function->getLocation(),
                                       Function->getDeclName(),
-                                      Proto->getExtInfo());
+                                      Proto->getExtProtoInfo());
     if (FunctionType->isNull() || Trap.hasErrorOccurred())
       return TDK_SubstitutionFailure;
   }
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -1716,7 +1716,9 @@
 
   NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
                         OldParm->getFunctionScopeIndex() + indexAdjustment);
-  
+
+  InstantiateAttrs(TemplateArgs, OldParm, NewParm);
+
   return NewParm;  
 }
 
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1637,6 +1637,20 @@
                                  RefQualifierKind RefQualifier,
                                  SourceLocation Loc, DeclarationName Entity,
                                  FunctionType::ExtInfo Info) {
+  FunctionProtoType::ExtProtoInfo EPI;
+  EPI.Variadic = Variadic;
+  EPI.HasTrailingReturn = HasTrailingReturn;
+  EPI.TypeQuals = Quals;
+  EPI.RefQualifier = RefQualifier;
+  EPI.ExtInfo = Info;
+
+  return BuildFunctionType(T, ParamTypes, Loc, Entity, EPI);
+}
+
+QualType Sema::BuildFunctionType(QualType T,
+                                 llvm::MutableArrayRef<QualType> ParamTypes,
+                                 SourceLocation Loc, DeclarationName Entity,
+                                 FunctionProtoType::ExtProtoInfo EPI) {
   if (T->isArrayType() || T->isFunctionType()) {
     Diag(Loc, diag::err_func_returning_array_function)
       << T->isFunctionType() << T;
@@ -1670,13 +1684,6 @@
   if (Invalid)
     return QualType();
 
-  FunctionProtoType::ExtProtoInfo EPI;
-  EPI.Variadic = Variadic;
-  EPI.HasTrailingReturn = HasTrailingReturn;
-  EPI.TypeQuals = Quals;
-  EPI.RefQualifier = RefQualifier;
-  EPI.ExtInfo = Info;
-
   return Context.getFunctionType(T, ParamTypes, EPI);
 }
 
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -714,10 +714,7 @@
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildFunctionProtoType(QualType T,
                                     llvm::MutableArrayRef<QualType> ParamTypes,
-                                    bool Variadic, bool HasTrailingReturn,
-                                    unsigned Quals,
-                                    RefQualifierKind RefQualifier,
-                                    const FunctionType::ExtInfo &Info);
+                                    const FunctionProtoType::ExtProtoInfo &EPI);
 
   /// \brief Build a new unprototyped function type.
   QualType RebuildFunctionNoProtoType(QualType ResultType);
@@ -4266,11 +4263,7 @@
       T->getNumArgs() != ParamTypes.size() ||
       !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
     Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
-                                                   T->isVariadic(),
-                                                   T->hasTrailingReturn(),
-                                                   T->getTypeQuals(),
-                                                   T->getRefQualifier(),
-                                                   T->getExtInfo());
+                                                   T->getExtProtoInfo());
     if (Result.isNull())
       return QualType();
   }
@@ -8832,7 +8825,7 @@
     return ExprError();
   }
 
-  const FunctionType *exprFunctionType = E->getFunctionType();
+  const FunctionProtoType *exprFunctionType = E->getFunctionType();
   QualType exprResultType =
       getDerived().TransformType(exprFunctionType->getResultType());
 
@@ -8847,9 +8840,7 @@
 
   QualType functionType =
     getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
-                                          oldBlock->isVariadic(),
-                                          false, 0, RQ_None,
-                                          exprFunctionType->getExtInfo());
+                                          exprFunctionType->getExtProtoInfo());
   blockScope->FunctionType = functionType;
 
   // Set the parameters on the block decl.
@@ -9068,16 +9059,11 @@
 QualType TreeTransform<Derived>::RebuildFunctionProtoType(
     QualType T,
     llvm::MutableArrayRef<QualType> ParamTypes,
-    bool Variadic,
-    bool HasTrailingReturn,
-    unsigned Quals,
-    RefQualifierKind RefQualifier,
-    const FunctionType::ExtInfo &Info) {
-  return SemaRef.BuildFunctionType(T, ParamTypes, Variadic,
-                                   HasTrailingReturn, Quals, RefQualifier,
+    const FunctionProtoType::ExtProtoInfo &EPI) {
+  return SemaRef.BuildFunctionType(T, ParamTypes,
                                    getDerived().getBaseLocation(),
                                    getDerived().getBaseEntity(),
-                                   Info);
+                                   EPI);
 }
 
 template<typename Derived>
Index: test/CodeGenObjCXX/arc-attrs.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/arc-attrs.mm
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fobjc-arc -O0 -o - %s | FileCheck %s
+
+id makeObject1() __attribute__((ns_returns_retained));
+id makeObject2() __attribute__((ns_returns_retained));
+void releaseObject(__attribute__((ns_consumed)) id);
+
+// CHECK: define void @_Z10sanityTestv
+void sanityTest() {
+  // CHECK: [[X:%.*]] = alloca i8*, align 8
+  // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z11makeObject1v()
+  // CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8
+  id x = makeObject1();
+
+  // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z11makeObject2v()
+  // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
+  releaseObject(makeObject2());
+
+  // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+  // CHECK-NEXT: ret void
+}
+
+
+template <typename T>
+T makeObjectT1() __attribute__((ns_returns_retained));
+template <typename T>
+T makeObjectT2() __attribute__((ns_returns_retained));
+
+template <typename T>
+void releaseObjectT(__attribute__((ns_consumed)) T);  
+
+// CHECK: define void @_Z12templateTestv
+void templateTest() {
+  // CHECK: [[X:%.*]] = alloca i8*, align 8
+  // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectET_v()
+  // CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8
+  id x = makeObjectT1<id>();
+
+  // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectET_v()
+  // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
+  releaseObject(makeObjectT2<id>());
+
+  // CHECK-NEXT: [[OBJ3:%.*]] = call i8* @_Z11makeObject1v()
+  // CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvT_(i8* [[OBJ3]])
+  releaseObjectT(makeObject1());
+
+  // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+  // CHECK-NEXT: ret void
+}
Index: test/SemaObjCXX/arc-nsconsumed-errors.mm
===================================================================
--- test/SemaObjCXX/arc-nsconsumed-errors.mm
+++ test/SemaObjCXX/arc-nsconsumed-errors.mm
@@ -18,3 +18,35 @@
 blk1 c3 = ^void (__attribute((ns_consumed)) id, __attribute((ns_consumed)) id){};
 
 blk1 d4 = ^void (id, id) {}; // expected-error {{cannot initialize a variable of type '__strong blk1'}}
+
+
+typedef void (*releaser_t)(__attribute__((ns_consumed)) id);
+
+void normalFunction(id);
+releaser_t r1 = normalFunction; // expected-error {{cannot initialize a variable of type 'releaser_t'}}
+
+void releaser(__attribute__((ns_consumed)) id);
+releaser_t r2 = releaser; // no-warning
+
+template <typename T>
+void templateFunction(T) {} // expected-note {{candidate function}}
+releaser_t r3 = templateFunction<id>; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (id)'}}
+
+template <typename T>
+void templateReleaser(__attribute__((ns_consumed)) T) {}
+releaser_t r4 = templateReleaser<id>; // no-warning
+
+
+@class AntiRelease, ExplicitAntiRelease, ProRelease;
+
+template<>
+void templateFunction(__attribute__((ns_consumed)) AntiRelease *); // expected-error {{no function template matches function template specialization 'templateFunction'}}
+
+template<>
+void templateReleaser(AntiRelease *); // expected-error {{no function template matches function template specialization 'templateReleaser'}}
+
+template<>
+void templateReleaser(ExplicitAntiRelease *) {} // expected-error {{no function template matches function template specialization 'templateReleaser'}}
+
+template<>
+void templateReleaser(__attribute__((ns_consumed)) ProRelease *); // no-warning
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to