aaron.ballman created this revision.
aaron.ballman added a reviewer: rsmith.
aaron.ballman added a subscriber: cfe-commits.

When determining whether a function was written with a prototype, we would look 
at the type to see if it was something other than a FunctionType while the 
canonical type was a function with a prototype. We need to ignore attributed 
function types in this check, as they should not generate an incompatible 
function type in C. Fixing this introduced a secondary problem where we were 
assuming that K&R functions could not be attributed types when reporting 
old-style function definitions that are not preceded by a prototype.


https://reviews.llvm.org/D28166

Files:
  lib/Sema/SemaDecl.cpp
  test/Sema/knr-def-call.c
  test/Sema/warn-strict-prototypes.c


Index: test/Sema/warn-strict-prototypes.c
===================================================================
--- test/Sema/warn-strict-prototypes.c
+++ test/Sema/warn-strict-prototypes.c
@@ -60,3 +60,8 @@
 // K&R function definition with previous prototype declared is not diagnosed.
 void foo11(int p, int p2);
 void foo11(p, p2) int p; int p2; {}
+
+// PR31020
+void __attribute__((cdecl)) foo12(d) // expected-warning {{this old-style 
function definition is not preceded by a prototype}}
+  short d;
+{}
Index: test/Sema/knr-def-call.c
===================================================================
--- test/Sema/knr-def-call.c
+++ test/Sema/knr-def-call.c
@@ -39,3 +39,9 @@
   proto(42.1); // expected-warning{{implicit conversion from 'double' to 'int' 
changes value from 42.1 to 42}}
   (&proto)(42.1); // expected-warning{{implicit conversion from 'double' to 
'int' changes value from 42.1 to 42}}
 }
+
+// PR31020
+void func(short d) __attribute__((cdecl)); // expected-note{{previous 
declaration is here}}
+void __attribute__((cdecl)) func(d)
+  short d; // expected-warning{{promoted type 'int' of K&R function parameter 
is not compatible with the parameter type 'short' declared in a previous 
prototype}}
+{}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -7458,11 +7458,16 @@
     // Determine whether the function was written with a
     // prototype. This true when:
     //   - there is a prototype in the declarator, or
-    //   - the type R of the function is some kind of typedef or other 
reference
-    //     to a type name (which eventually refers to a function type).
+    //   - the type R of the function is some kind of typedef or other non-
+    //     attributed reference to a type name (which eventually refers to a
+    //     function type).
+    const Type *NonAttributedFTy = R.getTypePtr();
+    while (const auto *AttrTy = NonAttributedFTy->getAs<AttributedType>()) {
+      NonAttributedFTy = AttrTy->getModifiedType().getTypePtr();
+    }
     bool HasPrototype =
       (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
-      (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+      (!isa<FunctionType>(NonAttributedFTy) && R->isFunctionProtoType());
 
     NewFD = FunctionDecl::Create(SemaRef.Context, DC,
                                  D.getLocStart(), NameInfo, R,
@@ -11950,6 +11955,11 @@
           !LangOpts.CPlusPlus) {
         TypeSourceInfo *TI = FD->getTypeSourceInfo();
         TypeLoc TL = TI->getTypeLoc();
+        // The type location may be attributed; strip the attributes to get to
+        // the function type location.
+        while (auto ATL = TL.getAs<AttributedTypeLoc>()) {
+          TL = ATL.getModifiedLoc();
+        }
         FunctionTypeLoc FTL = TL.castAs<FunctionTypeLoc>();
         Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1;
       }


Index: test/Sema/warn-strict-prototypes.c
===================================================================
--- test/Sema/warn-strict-prototypes.c
+++ test/Sema/warn-strict-prototypes.c
@@ -60,3 +60,8 @@
 // K&R function definition with previous prototype declared is not diagnosed.
 void foo11(int p, int p2);
 void foo11(p, p2) int p; int p2; {}
+
+// PR31020
+void __attribute__((cdecl)) foo12(d) // expected-warning {{this old-style function definition is not preceded by a prototype}}
+  short d;
+{}
Index: test/Sema/knr-def-call.c
===================================================================
--- test/Sema/knr-def-call.c
+++ test/Sema/knr-def-call.c
@@ -39,3 +39,9 @@
   proto(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}}
   (&proto)(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}}
 }
+
+// PR31020
+void func(short d) __attribute__((cdecl)); // expected-note{{previous declaration is here}}
+void __attribute__((cdecl)) func(d)
+  short d; // expected-warning{{promoted type 'int' of K&R function parameter is not compatible with the parameter type 'short' declared in a previous prototype}}
+{}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -7458,11 +7458,16 @@
     // Determine whether the function was written with a
     // prototype. This true when:
     //   - there is a prototype in the declarator, or
-    //   - the type R of the function is some kind of typedef or other reference
-    //     to a type name (which eventually refers to a function type).
+    //   - the type R of the function is some kind of typedef or other non-
+    //     attributed reference to a type name (which eventually refers to a
+    //     function type).
+    const Type *NonAttributedFTy = R.getTypePtr();
+    while (const auto *AttrTy = NonAttributedFTy->getAs<AttributedType>()) {
+      NonAttributedFTy = AttrTy->getModifiedType().getTypePtr();
+    }
     bool HasPrototype =
       (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
-      (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+      (!isa<FunctionType>(NonAttributedFTy) && R->isFunctionProtoType());
 
     NewFD = FunctionDecl::Create(SemaRef.Context, DC,
                                  D.getLocStart(), NameInfo, R,
@@ -11950,6 +11955,11 @@
           !LangOpts.CPlusPlus) {
         TypeSourceInfo *TI = FD->getTypeSourceInfo();
         TypeLoc TL = TI->getTypeLoc();
+        // The type location may be attributed; strip the attributes to get to
+        // the function type location.
+        while (auto ATL = TL.getAs<AttributedTypeLoc>()) {
+          TL = ATL.getModifiedLoc();
+        }
         FunctionTypeLoc FTL = TL.castAs<FunctionTypeLoc>();
         Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1;
       }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to