diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e37a0b5e41..8f9a8f9974 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -914,6 +914,10 @@ def err_cconv_knr : Error< "function with no prototype cannot use %0 calling convention">; def err_cconv_varargs : Error< "variadic function cannot use %0 calling convention">; +def err_regparm_mismatch : Error<"function declared with with regparm(%0) " + "attribute was previously declared %plural{0:without the regparm|1:" + "with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the" + "regparm}1 attribute">; def warn_impcast_vector_scalar : Warning< "implicit cast turns vector to scalar: %0 to %1">, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9e31a54372..528cc65abf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1057,13 +1057,27 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } // FIXME: diagnose the other way around? - if (OldType->getNoReturnAttr() && - !NewType->getNoReturnAttr()) { + if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) { NewQType = Context.getNoReturnType(NewQType); New->setType(NewQType); assert(NewQType.isCanonical()); } + // Merge regparm attribute. + if (OldType->getRegParmType() != NewType->getRegParmType()) { + if (NewType->getRegParmType()) { + Diag(New->getLocation(), diag::err_regparm_mismatch) + << NewType->getRegParmType() + << OldType->getRegParmType(); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewQType = Context.getRegParmType(NewQType, OldType->getRegParmType()); + New->setType(NewQType); + assert(NewQType.isCanonical()); + } + if (getLangOptions().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: diff --git a/test/CodeGen/regparm.c b/test/CodeGen/regparm.c index b60f8c70d7..ec5cbab16a 100644 --- a/test/CodeGen/regparm.c +++ b/test/CodeGen/regparm.c @@ -14,6 +14,11 @@ FType bar; static void FASTCALL reduced(char b, double c, foo* d, double e, int f); +// PR7025 +void FASTCALL f1(int i, int j, int k); +// CHECK: define void @f1(i32 inreg %i, i32 inreg %j, i32 %k) +void f1(int i, int j, int k) { } + int main(void) { // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.anon* inreg null diff --git a/test/Sema/attr-regparm.c b/test/Sema/attr-regparm.c index 045a41396e..4049e0e8a1 100644 --- a/test/Sema/attr-regparm.c +++ b/test/Sema/attr-regparm.c @@ -1,7 +1,11 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s -__attribute((regparm(2))) int x(void); -__attribute((regparm(1.0))) int x(void); // expected-error{{'regparm' attribute requires integer constant}} -__attribute((regparm(-1))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} -__attribute((regparm(5))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} -__attribute((regparm(5,3))) int x(void); // expected-error{{attribute requires 1 argument(s)}} +__attribute((regparm(2))) int x0(void); +__attribute((regparm(1.0))) int x1(void); // expected-error{{'regparm' attribute requires integer constant}} +__attribute((regparm(-1))) int x2(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5))) int x3(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5,3))) int x4(void); // expected-error{{attribute requires 1 argument(s)}} + +void __attribute__((regparm(3))) x5(int); +void x5(int); // expected-note{{previous declaration is here}} +void __attribute__((regparm(2))) x5(int); // expected-error{{function declared with with regparm(2) attribute was previously declared with the regparm(3) attribute}} diff --git a/test/SemaCXX/attr-regparm.cpp b/test/SemaCXX/attr-regparm.cpp new file mode 100644 index 0000000000..b98631abe5 --- /dev/null +++ b/test/SemaCXX/attr-regparm.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR7025 +struct X0 { + void __attribute__((regparm(3))) f0(); + void __attribute__((regparm(3))) f1(); + void __attribute__((regparm(3))) f2(); // expected-note{{previous declaration is here}} + void f3(); // expected-note{{previous declaration is here}} +}; + +void X0::f0() { } +void __attribute__((regparm(3))) X0::f1() { } +void __attribute__((regparm(2))) X0::f2() { } // expected-error{{function declared with with regparm(2) attribute was previously declared with the regparm(3) attribute}} +void __attribute__((regparm(2))) X0::f3() { } // expected-error{{function declared with with regparm(2) attribute was previously declared without the regparm attribute}}