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()) { + NonAttributedFTy = AttrTy->getModifiedType().getTypePtr(); + } bool HasPrototype = (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || - (!isa(R.getTypePtr()) && R->isFunctionProtoType()); + (!isa(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()) { + TL = ATL.getModifiedLoc(); + } FunctionTypeLoc FTL = TL.castAs(); Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1; } 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: 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; +{}